Неинициализированное значение было создано распределением кучи
Я преследовал эту ошибку, и я просто не понимаю ее. Я забыл какой-то базовый 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"? Есть идеи? Спасибо заранее!
Ответы
Ответ 1
У вас есть две ошибки в строке 104,
strncpy(inputCopy, input, strlen(input)*sizeof(char));
Вам нужно предоставить strncpy место для завершения null, поэтому оно должно быть strlen(input)+1
strncpy не гарантирует, что выходной буфер не будет завершен, что похоже на ошибку в strncpy, но это не так. Он был разработан таким образом. То, что было создано strncpy, это скопировать строку в выходной буфер, а затем заполнить остальную часть буфера нулями. Он не разработан как "безопасный strcpy"
Другая ошибка заключается в том, что strncpy принимает число символов, а не количество байтов, поэтому неверно умножать на sizeof(char).
. Поскольку sizeof (char) == 1, это на самом деле не вызывает проблем, но по-прежнему остается неправильным намерением.
Вы были правильно умножить на sizeof(char)
в malloc
в строке 99, так как malloc
требуется количество байтов.
Ответ 2
strncpy не будет помещать символ окончания 0, поскольку он копирует не более N символов (где N - это параметр 3). Поскольку вы указали длину и не включили +1 для завершения 0, она не была добавлена.
Итак, если у вас есть буфер из N байтов, правильное использование strncpy таково:
strncpy(dest, src, N - 1);
dest[N - 1] = '\0';
strncpy - странная функция. Кроме того, что не обещаю написать завершающий 0, он всегда будет писать ровно N символов в буфер назначения. Если src меньше, то N, strncpy на самом деле займет время, чтобы заполнить весь остаток буфера 0.
Ответ 3
Я считаю, что ваш strncpy
не помещает завершающий нулевой символ в конец строки, поэтому printf запускается с конца выделенной памяти.