使用free()时读取大小4无效

时间:2015-08-06 13:35:41

标签: c memory-management valgrind free

我是C和valgrind的新人并试图学习它们。 当我使用以下功能时:

void die(const char *message,struct Connection *conn){
    if (conn){
        free(conn->file);
        free(conn->db);
        free(conn);
    }
    if (errno){
        perror(message);
    }else{
        printf("ERROR:$s\n",message);
    }
    exit(1);
}

从结构中打印错误和释放内存(这是他们的声明):

struct Address{
    int id;
    int set;
    char name[MAX_DATA];
    char email[MAX_DATA];
};

struct Database{
    struct Address rows[MAX_ROWS];
};

struct Connection{
    FILE *file;
    struct Database *db;
};

我从valgrind那里得到了这样的错误:

==15471== 2 errors in context 61 of 62
==15471== Invalid read of size 4
==15471==     at 0x4EA5889: _IO_default_setbuf (genops.c:567)
==15471==     by 0x4EA4928: _IO_file_setbuf@@GLIBC_2.2.5 (fileops.c:454)
==15471==     by 0x4EA6C32: _IO_unbuffer_write (genops.c:979)
==15471==     by 0x4EA6C32: _IO_cleanup (genops.c:1019)
==15471==     by 0x4E67F14: exit (exit.c:100)
==15471==     by 0x40097F: die (ex17.c:33)
==15471==     by 0x400DF4: Database_get (ex17.c:105)
==15471==     by 0x40102F: main (ex17.c:139)
==15471== Addres 0x51d53f0 is 0 bytes inside a block of size 568 free'd
==15471==     at 0x4C2845A: free (vg_replace_malloc.c:473)
==15471==     by 0x40091D: die (ex17.c:25)
==15471==     by 0x400DF4: Database_get (ex17.c:105)
==15471==    by 0x40102F: main (ex17.c:139)

但是在执行valgrind时,我没有内存错误。 可以将NULL传递给free()吗?这真的是一个错误,因为男人说free(NULL)什么都不做?

抱歉英文不好。

3 个答案:

答案 0 :(得分:3)

如果您不是libc,我不知道free FILE指针在哪里是合法的,你不是。无论你想要free(conn->file);意味着什么,这绝对不是这样做的方式。

发生的事情是你释放了一些你自己没有释放的内存,退出时libc会自行清理打开的文件并崩溃,因为它会触及你已经破坏的内存。

如果我不得不猜测,那你可能意味着fclose

答案 1 :(得分:2)

你没有free FILE *指针,因为你也不会malloc它。你将一个FILE *指针传递给fclose(),它将为你销毁它(如果存在这样的内存,也会释放内存 - 因为它没有定义一个FILE *指针指向内存已由malloc分配,只有在这种情况下调用free才合法)。

此外,您还没有展示如何分配所有内存。当您仅使用conn分配malloc()并且不明确分配conn->db或将其设置为NULL时,其值未定义(malloc基本上返回内存中填充了"随机字节"),因此在malloc之后conn->db的值可能是NULL(如果你很幸运,因为内存通常是零填充)或它可能是别的东西。如果要确保所有已分配的内存都为零,则始终需要使用calloc进行分配(因此所有布尔值均为假,所有整数值均为0且所有指针均为NULL)。

答案 2 :(得分:0)

第一件事:在我看来,这是一个非常经典的问题。也许您或应用程序尝试访问之前已释放的内存地址。这可能会导致崩溃。

但是对于你的具体情况: 不应释放文件指针。相反,您应该使用适当的Ansi C函数关闭文件,并再次将指针设置为NULL。

问题:您的应用程序是多线程的吗?

因为有人可能在您释放指针后尝试访问指针(另一个线程)。