C:Valgrind:使用大小为4的未初始化值和使用大小为4的未初始化值

Aus*_*ton 6 c valgrind

这两个错误将出现一个链表/低级文件读/ 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)
Run Code Online (Sandbox Code Playgroud)

这是函数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);
}
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚为什么会出现这种错误.从我读到的内容是因为我正在从strtok向char*分配东西,而没有为它们分配任何内存.不过这就是我过去的做法,我认为一切都很好.

jxh*_*jxh 6

正如其他人所猜测的那样,valgrind抱怨strtok正在使用未初始化的内存。然后问题转向为什么,因为它似乎是通过以下方式初始化的:

read(fdin, ara, 4096);
Run Code Online (Sandbox Code Playgroud)

但是,read()\0终止数据,而strtok期望\0终止的字符串。确保输入正确终止:

ssize_t result = read(fdin, ara, sizeof(ara)-1); /* leave room for '\0' */
ara[result > 0 ? result : 0] = '\0';
Run Code Online (Sandbox Code Playgroud)

memset(ara, 0, sizeof(ara));Lee Daniel Crocker的建议相当于相同类型的修复,但仅当文件包含少于sizeof(ara)字节的输入时才有效。如果您读取的文件有 4096 字节或更多的数据,您仍然会遇到类似的问题。然后,strtok将被迫扫描缓冲区的末尾以查找\0,从而导致未定义的行为。


Imr*_*err 1

读取的数据read末尾是否有空终止符?如果不是,那可能就是问题所在。