如何检查char *是否指向C中的字符串文字

我有一个结构

struct request { int code; char *message; }; 

我想要正确地自由。

我有以下function来做到这一点:

 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创建的消息。

没有标准函数可以让您知道指针是否是动态分配的。 你应该在你的结构中包含一个标志来告知你自己,或者只使用动态分配的字符串(在这种情况下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); 

那,并从free_request设置reqNULL将不会有任何影响。 您需要获取struct message**或在函数调用后自己执行。

没有办法判断你是否正在使用字符串文字(嗯,你可以将字符串文字放在由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()释放可以解决特殊情况。

我建议在struct request添加一个成员来指示request :: message是否是动态分配的,并在分配request::message的同时设置该成员,然后在释放内存之前检查它。 它在C中有点乱。

请注意,不仅是会导致问题的字符串文字,任何指向未通过malloc()或calloc()在堆上动态分配的数据的指针都会失败,因此只需检测“如果char指向C中的字符串文字” *即使它可以轻松完成也无济于事。

它是段错误的,因为包含"TEST"的内存位置(通常)是只读的而不是位于堆上(通常是因为它驻留在程序的某些只读部分)。 只给出一个char*指针,你将无法知道它是否指向free() able字符串。 相反,您应该为req->message分配一个缓冲区并复制字符。

 char* str = "TEST"; int len = strlen(str); req->message = malloc(len+1); strcpy(req->message, str); 

或者,您可以使用zneak建议的strdup()

如果你只是想确保释放malloc的内存,你可以打电话

 realloc(req->message,(size_t)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; 

是多余的。