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

时间:2010-08-03 16:45:08

标签: c string free

我有一个结构

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

6 个答案:

答案 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; 

是多余的。