这两个错误出现了链表/低级文件读/ strtok程序。
==10982== Use of uninitialised value of size 4
==10982== at 0x40C3899: strtok (strtok.S:197)
==10982== by 0x8048719: main (main.c:9)
==10982== Uninitialised value was created by a stack allocation
==10982== at 0x80487D2: buildList (functions.c:13)
==10982==
==10982== Use of uninitialised value of size 4
==10982== at 0x40C38C1: strtok (strtok.S:223)
==10982== by 0x8048719: main (main.c:9)
==10982== Uninitialised value was created by a stack allocation
==10982== at 0x80487D2: buildList (functions.c:13)
==10982==
==10982== Conditional jump or move depends on uninitialised value(s)
==10982== at 0x40C38C4: strtok (strtok.S:224)
==10982== by 0x8048719: main (main.c:9)
==10982== Uninitialised value was created by a stack allocation
==10982== at 0x80487D2: buildList (functions.c:13)
这是函数buildList
void buildList(int fdin, int lines)
{
char ara[4096];
int num;
double p;
read(fdin, ara, 4096);
char *nl = "\n";
char *ws = " ";
char *temp = strtok(ara, " ");
while(temp != NULL)
{
Stock *s = (Stock*)calloc(1, sizeof(Stock));
s->c.symbol = (char*)calloc(strlen(temp)+1, sizeof(char));
strcpy(s->c.symbol, temp);
temp = strtok(NULL, "\n");
s->c.name = (char*)calloc(strlen(temp)+1, sizeof(char));
strcpy(s->c.name, temp);
temp = strtok(NULL, "\n");
sscanf(temp, "%lf", &p);
temp = strtok(NULL, "\n");
s->price = p;
sscanf(temp, "%d", &num);
s->shares = num;
Node *n = (Node*)calloc(1, sizeof(Node));
n->data = s;
addOrdered(n);
temp = strtok(NULL, " ");
}
close(fdin);
}
我无法弄清楚为什么会出现这种错误。从我读到的内容是因为我正在从strtok向char *分配东西,而没有为它们分配任何内存。不过这就是我过去的做法,我认为一切都很好。
答案 0 :(得分:4)
正如其他人所推测的那样,valgrind
抱怨strtok
正在利用未初始化的记忆。然后问题转向为什么,因为它似乎正在被初始化:
read(fdin, ara, 4096);
但是,read()
没有\0
终止数据,而strtok
期望\0
终止字符串。确保输入正确终止:
ssize_t result = read(fdin, ara, sizeof[ara]-1); /* leave room for '\0' */
ara[result > 0 ? result : 0] = '\0';
Lee Daniel Crocker的memset(ara, 0, sizeof(ara));
建议相当于同样的修复,但只有在文件包含少于sizeof(ara)
个字节的输入时才有效。如果您从中读取的文件包含4096字节或更多数据,则仍会遇到类似问题。然后,strtok
将被强制扫描超过缓冲区的末尾以查找\0
,从而导致未定义的行为。
答案 1 :(得分:3)
read(fdin, ara, 4096);
......可以返回:
ara
未填写; ara
未填写; ara
的所有字节都没有填写。始终检查read()
的返回值。
char * temp = strtok(ara,“”);
$ man strtok
...
The strtok() function is used to isolate sequential tokens in a null-ter-
minated string, str. ...
没有任何内容可以保证ara
中包含空字符('\0'
),因此您无法有效地将其传递给strtok()
。如果您想确保其中包含char ara[4097]
,请在阅读后设为ara[4096] = '\0';
并执行'\0'
。
或者,更好的是,如果read()
的返回值在变量data_read
中,并且您已经检查过以确保它不是-1,那么执行ara[data_read] = '\0';
,将最后一个读取后的字节设置为'\0'
。
如果文件超过4096个字符并且您的read()
调用读入了多个行,并且另一行的开头,会发生什么?鉴于此,您可能需要考虑使用fopen()
打开文件并使用fgets()
来读取行。
答案 2 :(得分:1)
read
读取的数据末尾是否有空终结符?如果没有,那可能是个问题。