Неинициализированное значение было создано выделением кучи - PullRequest
13 голосов
/ 30 января 2010

Я гонялся за этой ошибкой, и я просто не понимаю. Я забыл какой-то базовый C или что-то еще?

==28357== Conditional jump or move depends on uninitialised value(s)
==28357==    at 0x4C261E8: strlen (mc_replace_strmem.c:275)
==28357==    by 0x4E9280A: puts (ioputs.c:36)
==28357==    by 0x400C21: handlePath (myshell.c:105)
==28357==    by 0x400B17: handleInput (myshell.c:69)
==28357==    by 0x400AAD: acceptInput (myshell.c:60)
==28357==    by 0x4009CF: main (myshell.c:33)
==28357==  Uninitialised value was created by a heap allocation
==28357==    at 0x4C25153: malloc (vg_replace_malloc.c:195)
==28357==    by 0x400BDE: handlePath (myshell.c:99)
==28357==    by 0x400B17: handleInput (myshell.c:69)
==28357==    by 0x400AAD: acceptInput (myshell.c:60)
==28357==    by 0x4009CF: main (myshell.c:33)
==28357==

(095) void handlePath(char *input) {
(096)     if(DEBUG_ON) { printf("%s%s\n", "DEBUG_HANDLEPATH: ", input); }
(097)
(098)     char *inputCopy = NULL;
(099)     inputCopy = (char *)malloc((strlen(input)+1)*sizeof(char));
(100)
(101)     if(inputCopy==NULL) {
(102)         die("malloc() failed in handlePath()");
(103)     }
(104)     strncpy(inputCopy, input, strlen(input)*sizeof(char));
(105)     printf("%s\n", inputCopy);
(106)     free(inputCopy);
(107)     return;
(108) }

Строка 96 печатает параметр "char * input" просто отлично (DEBUG_ON == 1), но строка 105 выдает ошибки valgrind (она отлично печатается в консоли) «char * input» происходит от getline (), захватывающего строку ввода, и в случае этой функции будет что-то вроде «path / test / path» без кавычек. Я могу распечатать и манипулировать им просто отлично в предыдущих функциях. Что не инициализировано в "char * inputCopy"? Есть идеи? Заранее спасибо!

Ответы [ 3 ]

13 голосов
/ 30 января 2010

У вас две ошибки в строке 104,

strncpy(inputCopy, input, strlen(input)*sizeof(char));

Вам нужно дать strncpy место для завершающего нуля, поэтому оно должно быть strlen(input)+1 strncpy не гарантирует, что выходной буфер будет пустым, что похоже на ошибку в strncpy, но это не так. Он был разработан, чтобы работать таким образом. Для чего был разработан strncpy, это скопировать строку в выходной буфер и затем заполнить оставшуюся часть буфера нулями . На самом деле это не «безопасный strcpy»

Ваша другая ошибка заключается в том, что strncpy принимает символ , а не число байтов, поэтому умножение на sizeof(char). некорректно. Так как sizeof (char) == 1, на самом деле это не вызывает проблем, но это все же неправильное намерение.

Вы были правильно умножены на sizeof(char) в malloc в строке 99, поскольку malloc требуется счетчик байтов.

4 голосов
/ 30 января 2010

strncpy не помещает завершающий символ 0, так как копирует не более N символов (где N - параметр 3). Поскольку вы указали длину и не указали +1 для завершающего 0, она не была добавлена.

Итак, если у вас есть буфер из N байтов, правильное использование strncpy таково:

strncpy(dest, src, N - 1);
dest[N - 1] = '\0';

strncpy - странная функция. Помимо того, что он не обещает написать завершающий 0, он всегда будет записывать ровно N символов в буфер назначения. Если src меньше, чем N, strncpy фактически займет время, чтобы заполнить весь остаток буфера нулями.

3 голосов
/ 30 января 2010

Я полагаю, что ваш strncpy не помещает завершающий нулевой символ в конец строки, поэтому printf запускается с конца выделенной памяти.

...