我有一个结构
struct request {
int code;
char *message;
};
我想要正确免费。
我有以下功能:
void free_request(struct request *req) {
if (req->message != NULL) {
free(req->message);
}
free(req);
req = NULL;
}
问题是当我尝试释放使用字符串文字创建的请求时,我从编译器得到“free():invalid pointer”/ segfault错误:
struct request *req;
req = malloc(sizeof(struct request));
req->message = "TEST";
free_request(req);
因为我想在不同的地方创建请求结构,一旦使用文字(在客户端)和一次使用我从套接字读取的*字符(在服务器端),我想知道是否有一个函数要做确保我不会尝试释放文字,同时仍然允许我释放我使用malloc创建的消息。
答案 0 :(得分:24)
没有标准函数可以让您知道指针是否动态分配。你应该在你的结构中包含一个标志来告知你自己,或者只使用动态分配的字符串(在这种情况下strdup
是你的朋友)。根据您的网络设置,使用strdup
可能更简单(说实话, 更简单地使用strdup
)。
使用strdup
:
struct message* req;
req = malloc(sizeof *req);
req->message = strdup("TEST");
free_request(req);
带一面旗帜:
struct message
{
int code;
char* message;
bool isStatic; // replace to 'char' if bool doesn't exist
};
void free_request(struct message* req)
{
if (!req->isStatic) free(req->message);
free(req);
}
struct message* req;
req = malloc(sizeof *req);
req->message = "TEST";
req->isStatic = 1;
free_request(req);
另外,在创建对象时不要忘记将已分配的内存归零。这可以为你节省很多麻烦。
req = malloc(sizeof *req);
memset(req, 0, sizeof *req);
这样,将req
设置为NULL
free_request
将不会产生任何影响。您需要使用struct message**
或在函数调用后自行完成。
答案 1 :(得分:5)
没有办法判断你是否正在使用字符串文字(嗯,你可以将字符串文字放在由GCC创建的自定义.section中,然后检查字符串指针以确定它是否包含在.section中。文字)。但是......使用简单的编程模式有更好的方法。
正常情况。对free(req)的调用将按预期工作:释放请求结构。
struct *req;
req = malloc(sizeof(*req));
req->message = "TEST";
在下文中,some_string
是您希望存储为请求消息的字符串。它可以是文字的,也可以是动态分配的。这在分配struct本身时为字符串分配内存(并且在释放struct时将自动释放)。
struct *req;
req = malloc(sizeof(*req)+strlen(some_string)+1);
req->message = (char *)&req[1];
strcpy(req->message, some_string);
free(req);
请注意,dynamic string
的上述分配方案是通用的,即使您不知道some_string
是否为文字,也可以使用它。因此,一个处理这两种情况的单一函数,以及free()
释放可以解决特殊情况。
答案 2 :(得分:4)
我建议将成员添加到struct request
以指示是否动态分配request :: message,并在分配request::message
的同时设置该成员,然后在释放内存之前检查它。它在C中有点乱。
请注意,不仅是会导致问题的字符串文字,任何指向未通过malloc()或calloc()在堆上动态分配的数据的指针都会失败,因此只需检测 “ char 指向C“* 中的字符串文字,即使它可以移植也无济于事。
答案 3 :(得分:2)
它是段错误的,因为包含"TEST"
的内存位置(通常)是只读的而不是位于堆上(通常因为它驻留在程序的某些只读部分)。只给出一个char*
指针,您将无法知道它是否指向一个free()
字符串。相反,您应该为req->message
分配缓冲区并复制字符。
char* str = "TEST";
int len = strlen(str);
req->message = malloc(len+1);
strcpy(req->message, str);
或者,您可以按照zneak的建议使用strdup()
。
答案 4 :(得分:0)
如果您只是想确保释放malloc的内存,可以调用
realloc(req->message,(size_t)0)
如果内存库实现是健壮的,它应该可以工作。
答案 5 :(得分:0)
看看:
struct request *req;
req = calloc(1,sizeof(struct request));
strcpy(req->message = malloc(strlen("TEST")+1),"TEST");
free_request(req);
严格符合ANSI C标准。 strdup不是ANSI C。
req = NULL;
是多余的。