Указатель на символ приводит к неправильному выводу - PullRequest
2 голосов
/ 23 января 2012

У меня проблема с выводом char ptr. Ниже приведен пример кода, который я пытаюсь выполнить ..

struct DeviceInfo{

char * name;
int id;

};
void testFunc(DeviceInfo *info){

    char temp[50] = "test input";
    info->name = temp;

}
void main(){

    DeviceInfo deviceInfo;
    testFunc(&deviceInfo);
    std::cout<<"Output is "<<deviceInfo.name;


}

Вывод, который я получаю в основном, какой-то странный .... во время отладки я обнаружил, что когда «test.name» передается в выходной поток, это не только выдает вывод мусора, но также изменяет значение "name" для объекта "deviceInfo" на это значение мусора ... это своего рода тестовый сценарий, но в реальном приложении этот testFunc должен выполняться точно так же, т. е. константной символьной строке должно быть присвоено имя char ptr.

Я пытался поставить '\ 0' в конце char temp, например, temp [strlen (temp)] = '\ 0';

но все равно не работает

Любая помощь приветствуется ...

Раз

Ответы [ 6 ]

5 голосов
/ 23 января 2012

Это сбой, потому что вы назначаете указатель на автоматическую переменную для члена структуры с другой областью действия (и, следовательно, с другим сроком жизни). temp будет уничтожен в конце testFunc, и дальнейший доступ к нему является незаконным.

4 голосов
/ 23 января 2012

Вот почему у нас есть строковый класс.

struct DeviceInfo{
    std::string name;
    int id;
};

void testFunc(DeviceInfo *info){    
    info->name = "test_input";
}

int main(){
    DeviceInfo deviceInfo;
    testFunc(&deviceInfo);
    std::cout<<"Output is "<<deviceInfo.name;
}
4 голосов
/ 23 января 2012

temp - это переменная, выделенная стеком, она будет уничтожена после возврата testFunc().

Таким образом, char* будет указывать на уничтоженную память.

Это вызывает неопределенное поведение.

3 голосов
/ 23 января 2012

Вы храните указатель на локальное хранилище, которое исчезает, когда testFunc() выходит из области видимости.

Правильный путь для константной строки:

info->name = "test input";

или для чего-либоболее динамичный:

info->name = strdup("test input");

Вы также можете не указывать name в указателе, а вместо этого иметь char name[50]; в структуре, а затем просто сделать:

strcpy(info->name, "test input");

ЭтоБыло бы также целесообразно использовать версию с учетом размера, если она у вас есть:

snprintf(info->name, sizeof info->name, "%s", "test input");

Обратите внимание, что это предполагает решение для массива, sizeof info->name не будет иметь смысла, если name все еще является указателем.

1 голос
/ 23 января 2012

Вы назначаете указатель на временный массив.Как только testFunc() вернется, ваш временный массив будет уничтожен, а указатель info->name будет указывать на случайную память.

0 голосов
/ 23 января 2012
char *temp = "test input";
info->name = (char*)malloc(sizeof(char) * strlen(temp) + 1); // Include room for \0    
strcpy(info->name, temp);

вместо:

char temp[50] = "test input"; 
info->name = temp; 

Ваш char temp[50] больше не действителен после возврата функции.

...