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

时间:2010-01-30 06:08:07

标签: c pointers malloc valgrind strncpy

我一直在追逐这个bug,我只是不明白。我忘记了一些基本的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 个答案:

答案 0 :(得分:13)

你在第104行有两个错误,

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

你需要为终止null赋予strncpy空间,所以它应该是strlen(input)+1 strncpy不保证将输出缓冲区空终止,这似乎是strncpy中的一个错误,但事实并非如此。它旨在以这种方式工作。 strncpy的目的是将字符串复制到输出缓冲区,然后用零填充缓冲区的其余部分。它实际上并不是设计为'safe strcpy'

你的另一个错误是strncpy将字符计算为字节数,因此乘以sizeof(char).是不正确的。由于sizeof(char)== 1,这实际上不会导致问题,但仍然是错误的意图。

由于sizeof(char)需要字节数,因此在第99行的malloc中乘以malloc是正确的。

答案 1 :(得分:4)

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来填充缓冲区的其余部分。

答案 2 :(得分:3)

我相信你的strncpy没有在字符串的末尾放置一个终止空字符,所以printf在分配的内存的末尾运行。