我是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)
什么都不做?
抱歉英文不好。
答案 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。
问题:您的应用程序是多线程的吗?
因为有人可能在您释放指针后尝试访问指针(另一个线程)。