使用 free() 时大小为 4 的无效读取
invalid read of size 4 when using 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)
什么都不做?
抱歉英语不好。
您没有 free
一个 FILE *
指针,因为您也没有 malloc
它。您将 FILE *
指针传递给 fclose()
,这将为您销毁它(并且释放内存,如果这样的内存确实存在 - 因为它没有定义 FILE *
指针指向内存已由 malloc
分配,只有在这种情况下调用 free
才是合法的。
你也没有说明你是如何分配所有内存的。当您仅使用 malloc()
分配 conn
而未显式分配 conn->db
或将其设置为 NULL
时,其值未定义(malloc
returns 基本上是用 "random bytes") 填充的内存,所以在 malloc
之后 conn->db
的值可能是 NULL
(如果你幸运的话,因为内存经常被零填充)或者它可能是别的东西。如果你想确保所有分配的内存都归零(因此所有布尔值都是假的,所有整数值都是 0 并且所有指针都是 NULL
),你总是需要使用 calloc
进行分配。
如果您不是 libc,我不知道在什么情况下 free
ing 一个 FILE
指针是合法的,而您不是。无论您打算 free(conn->file);
表达什么意思,这绝对不是正确的做法。
发生的情况是,您释放了一些不属于您的内存,并且在退出时 libc 会自行清理打开的文件,并且崩溃,因为它触及了您已经毁掉的内存。
如果非要我猜的话,你可能指的是 fclose
。
第一件事:在我看来这是一个非常经典的问题。也许您或应用程序试图访问之前已释放的内存地址。这可能会导致崩溃。
但对于您的具体情况:
不应释放文件指针。相反,您应该使用适当的 Ansi C 函数关闭文件并再次将指针设置为 NULL。
问题:您的应用程序是多线程的吗?
因为在您释放指针(另一个线程)后,有人可能会尝试访问它。
我是 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)
什么都不做?
抱歉英语不好。
您没有 free
一个 FILE *
指针,因为您也没有 malloc
它。您将 FILE *
指针传递给 fclose()
,这将为您销毁它(并且释放内存,如果这样的内存确实存在 - 因为它没有定义 FILE *
指针指向内存已由 malloc
分配,只有在这种情况下调用 free
才是合法的。
你也没有说明你是如何分配所有内存的。当您仅使用 malloc()
分配 conn
而未显式分配 conn->db
或将其设置为 NULL
时,其值未定义(malloc
returns 基本上是用 "random bytes") 填充的内存,所以在 malloc
之后 conn->db
的值可能是 NULL
(如果你幸运的话,因为内存经常被零填充)或者它可能是别的东西。如果你想确保所有分配的内存都归零(因此所有布尔值都是假的,所有整数值都是 0 并且所有指针都是 NULL
),你总是需要使用 calloc
进行分配。
如果您不是 libc,我不知道在什么情况下 free
ing 一个 FILE
指针是合法的,而您不是。无论您打算 free(conn->file);
表达什么意思,这绝对不是正确的做法。
发生的情况是,您释放了一些不属于您的内存,并且在退出时 libc 会自行清理打开的文件,并且崩溃,因为它触及了您已经毁掉的内存。
如果非要我猜的话,你可能指的是 fclose
。
第一件事:在我看来这是一个非常经典的问题。也许您或应用程序试图访问之前已释放的内存地址。这可能会导致崩溃。
但对于您的具体情况: 不应释放文件指针。相反,您应该使用适当的 Ansi C 函数关闭文件并再次将指针设置为 NULL。
问题:您的应用程序是多线程的吗?
因为在您释放指针(另一个线程)后,有人可能会尝试访问它。