C 未初始化的值是由堆分配创建的

C 未初始化的值是由堆分配创建的,c,pointers,malloc,valgrind,strncpy,C,Pointers,Malloc,Valgrind,Strncpy,我一直在追这个虫子,但我就是不明白。我忘了一些基本的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 (mysh

我一直在追这个虫子,但我就是不明白。我忘了一些基本的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”有什么未初始化的地方?有什么想法吗?提前谢谢

我相信您的
strncpy
没有在字符串的末尾添加终止空字符,因此printf正在从分配的内存的末尾运行。

第104行有两个错误

strncpy(inputCopy, input, strlen(input)*sizeof(char));
您需要为终止null提供strncpy空间,因此它应该是
strlen(输入)+1
strncpy不能保证输出缓冲区null终止,这看起来像是strncpy中的一个bug,但事实并非如此。它就是这样设计的。strncpy的设计目的是将字符串复制到输出缓冲区中,然后用零填充缓冲区的其余部分。它并不是真正设计为“安全strcpy”

您的另一个错误是strncpy采用字符计数而不是字节计数,因此乘以
sizeof(char)是不正确的。
。由于sizeof(char)==1,这实际上并没有引起问题,但仍然是错误的意图


在第99行的
malloc
中用
sizeof(char)
相乘是正确的,因为
malloc
需要一个字节计数。

strncpy不会放置终止的0字符,因为它最多复制N个字符(其中N是3个参数)。由于您指定了长度,并且没有为终止0包含+1,因此未添加该长度

因此,假设您有一个N字节的缓冲区,strncpy的正确用法如下:

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

strncpy是一个奇怪的函数。除了不承诺写入终止0之外,它还将始终向目标缓冲区写入正好N个字符。如果src小于N,strncpy实际上会花时间用0填充整个剩余的缓冲区。

愚蠢的我!我这边发生了一起严重的RTFM事件。谢谢这很好地解决了这个问题。
sizeof(char)==1
,但明确无误。@ephemient:同意,尽管我会编写sizeof(inputCopy[0])而不是sizeof(char)。@ephemient:这与将
1*
放在变量前面是一样的:无用且容易混淆。我想最好把杂物放在外面。接得好。此外,strncpy无论如何都应该是strcpy。