简体   繁体   English

带有realloc的程序在Valgrind中表现不同

[英]Program with realloc behave differently in Valgrind

I wrote a function to read a string with fgets that uses realloc() to make the buffer grow when needed: 我编写了一个函数来读取带有fgets的字符串,该字符串在需要时使用realloc()使缓冲区增长:

char * read_string(char * message){
    printf("%s", message);
    size_t buffsize = MIN_BUFFER;
    char *buffer = malloc(buffsize);
    if (buffer == NULL) return NULL;
    char *p;
    for(p = buffer ; (*p = getchar()) != '\n' && *p != EOF ; ++p)
        if (p - buffer == buffsize - 1) {
            buffer = realloc(buffer, buffsize *= 2) ;
            if (buffer == NULL) return NULL;
        }
    *p = 0;
    p = malloc(p - buffer + 1);
    if (p == NULL) return NULL;
    strcpy(p, buffer);
    free(buffer);
    return p;
}

I compiled the program and tried it, and it worked like expected. 我编译了程序并进行了尝试,它的工作与预期的一样。 But when I run it with valgrind, the function returns NULL when the read string is >= MIN_BUFFER and valgrind says: 但是当我使用valgrind运行它时,当读取的字符串> = MIN_BUFFER时,该函数返回NULL,并且valgrind说:

 (...) ==18076== Invalid write of size 1 ==18076== at 0x8048895: read_string (programme.c:73) ==18076== by 0x804898E: main (programme.c:96) ==18076== Address 0x41fc02f is 0 bytes after a block of size 7 free'd ==18076== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==18076== by 0x8048860: read_string (programme.c:76) (...) ==18076== Warning: silly arg (-48) to malloc() (...) 

I added a printf statement between *p=0; 我在* p = 0之间添加了一条printf语句; and p=malloc... and it confirmed that the arg passed had a value of -48. 和p = malloc ...并确认传递的arg的值为-48。 I didn't know that programs don't run the same way when launched alone and with valgrind. 我不知道单独使用valgrind启动程序时,它们的运行方式不同。 Is there something wrong in my code or is it just a valgrind bug? 我的代码有什么问题吗?还是只是valgrind错误?

When you realloc the buffer, your pointer 'p' still points at the old buffer. 当您重新分配缓冲区时,指针“ p”仍指向旧缓冲区。

That will stomp memory, and also cause future allocations to use bogus values. 这将消耗内存,并导致将来的分配使用伪造的值。

As man 3 realloc says 正如人3重新分配说

...The function may move the memory block to a new location. ...该功能可能会将存储块移动到新位置。

What this means, is that 这是什么意思

p = malloc(p - buffer + 1);

is the problem. 是问题。 If realloc() was called, buffer might be pointing to a new block of memory and expression 如果调用了realloc(),则缓冲区可能指向新的内存和表达式块

(p - buffer)

does not make any sense. 没有任何意义。

realloc returns a pointer to a new buffer of the requested size with the same contents as the pointer passed in, assuming that the pointer passed in was previously returned by malloc or realloc . realloc返回一个指向所请求大小的新缓冲区的指针,该缓冲区的内容与传入的指针相同,并假定传入的指针先前由mallocrealloc返回。 It does not guarantee that it's the same pointer. 它不能保证它是相同的指针。 Valgrind very likely modifies the behavior of realloc , but keeps it within the specification. Valgrind很可能会修改realloc的行为,但会将其保留在规范内。

Since you are resizing memory in a loop, you would be better served by tracking your position in buffer as an offset from the beginning of buffer rather than a pointer. 既然你是在一个循环中调整大小的内存,您将得到更好的通过跟踪你的位置担任buffer作为从开始偏移buffer ,而不是一个指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM