为什么我得到 free(): invalid pointer?

Why am I getting free(): invalid pointer?

我目前正在阅读 Robert Love 的 Linux System Programming,并且一直停留在处理所有五个错误情况的 read() 示例上。我收到 free(): invalid pointer 错误。我假设它与推进缓冲区有关,以防读取未完成。

如果我存储偏移量和 return 指向其原始位置的指针,它就会起作用。书中没有提到这一点。有没有更好的方法?

#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int main()
{

    int fd;

    if( (fd = open("someFile.txt", O_CREAT | O_WRONLY | O_TRUNC, 0664)) < 0)
        perror("open for write");

    char * text =  "This is an example text";
    write(fd, text, strlen(text));

    close(fd);

    if( (fd = open("someFile.txt", O_RDONLY)) < 0)
        perror("open");

    char *buf; 

    if( (buf = (char *) calloc(50, sizeof(char))) == NULL )
        perror("calloc");

    int len = 50;
    ssize_t ret;

    /* If I store the offset in a variable it works */

    off_t offset = 0;

    while (len != 0 && (ret = read (fd, buf, len)) != 0) {
        if (ret == -1) {
            if (errno == EINTR)
                continue;
            perror ("read");
            break;
        }

        len -= ret;
        buf += ret;
        offset += ret;  // Offset stored here

    }

    if( close(fd) == -1 )
        perror("close");

    buf -= offset;     // Here I return the pointer to its original position
    free(buf);

    return 0;
}


此代码中存在多个错误。

首先,perror 没有被正确使用,因为它只打印一个错误——这里也应该有代码来中止错误,所以后续代码不会尝试使用来自操作的结果失败。

其次,只有calloc的结果才能免费赠送。结果保存在 buf 中,但随后的代码更改了 buf 的值并尝试释放更改后的值。将更改存储在 offset 中应该可以解决此问题,但这充其量是一种容易出错的解决方案。如果您有多个修改 buf 的代码路径,则必须确保每个代码路径也以相同的方式修改偏移量。

更好的方法是不修改 buf,而是在读取中使用第二个指针变量,该变量初始化为 buf 的值,然后在每次读取后修改。

正如所指出的,给 calloc 的数字与 len 的初始化数字不同。这是滥用幻数的完美示例。 20 和 50 都应该用相同的符号(变量或常量或#define)替换,这样你就不会得到缓冲区溢出错误。