C中的realloc()问题。总是挂起但编译得很好

时间:2010-06-29 00:53:15

标签: c memory-management pointers buffer realloc

我在使用一个旨在成为字符串缓冲区的程序时遇到了一些问题,特别是此函数用于使用字符串cstr重置缓冲区。如果cstr为null,则需要将内容重置为空char'\ 0'。它总是挂在第二组realloc上,它正在调整大小buf->内容我不知道为什么会这样。任何帮助都会很棒。

结构:

typedef struct strbuf {
     char   *contents;
     size_t  length;  
} StringBuffer;

调用
strbuf_reset(sb, NULL)

这是有问题的strbuf_reset函数。

StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if(buf == NULL)
    return NULL;

StringBuffer *tempBuf = NULL ;

if(cstr == NULL)
    tempBuf = (StringBuffer*)realloc(buf,sizeof(StringBuffer) + sizeof(char));
else
    tempBuf = (StringBuffer*)realloc(buf,sizeof(buf) + strlen(cstr)*sizeof(char));

if(tempBuf == NULL)
    return NULL;

if(cstr == NULL)
    tempBuf->contents = (char*)realloc(buf->contents,sizeof(char));
else
    tempBuf->contents = (char*)realloc(buf->contents,(sizeof(buf->contents) + strlen(cstr)*sizeof(char) + 1));

if(tempBuf->contents == NULL){
    free(tempBuf);
    return NULL;
}
buf = tempBuf;

if(cstr == NULL)
   buf->contents = '\0';
else
   strcat(buf->contents,cstr);

buf->length = strlen(buf->contents);    

return buf;
 }

我相信建议的改变......

StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if(buf == NULL)
    return NULL;

StringBuffer *tempBuf = NULL ;

if(cstr == NULL)
    tempBuf = (StringBuffer*)realloc(buf,sizeof(StringBuffer) + sizeof(char) + 10);
else
    tempBuf = (StringBuffer*)realloc(buf,sizeof(buf) + strlen(cstr)*sizeof(char)+ 1);

if(tempBuf != NULL)
    buf = tempBuf;
else
    return NULL;    

if(cstr == NULL)
    tempBuf->contents = (StringBuffer*)realloc(buf->contents,sizeof(StringBuffer) + sizeof(char) + 10);
else
    tempBuf->contents = (StringBuffer*)realloc(buf->contents,sizeof(buf) + strlen(cstr)*sizeof(char)+ 1);

if(tempBuf != NULL)
    buf->contents = tempBuf->contents;
else
    return NULL;

if(cstr == NULL)
   buf->contents = '\0';
else
   strcat(buf->contents,cstr);

buf->length = strlen(buf->contents);    

return buf;
 }

3 个答案:

答案 0 :(得分:7)

您似乎不明白realloc的作用。

应该考虑它的方式(至少就扩大而言)是,它分配一个新缓冲区,将旧数据复制到其中,然后释放旧缓冲区

旧的指针然后无效如果你在以后尝试再次使用它时崩溃就不应该感到惊讶。

您应该立即将返回的值分配回旧指针,因此它仍然指向有效数据。

答案 1 :(得分:1)

您正在为StringBuffer中的字符串分配额外空间。我只是假设buf->内容应该指向额外分配的空间。如果不是这样,那么为什么在StringBuffer中分配额外的空间?

如果buf->内容已经指向为StringBuffer分配的内存,尝试重新分配它会将内存系统抛入崩溃/挂起/损坏堆状态,因为你将重新分配一个永远不会出现的指针分配

我认为结构看起来不应该尝试重新分配buf->内容:

struct StringBuffer {
    size_t length;
    char contents[1];
};

然后,您只需将字符串复制到那里,而不是重新分配buf->内容,而StringBuffer的realloc会处理所有内存。

答案 2 :(得分:1)

由于您要覆盖StringBuffer的内容,因此使用realloc毫无意义。它不会为您节省任何内存分配,而是会复制您想要覆盖的旧数据。使用普通的malloc和free。

使用原始结构

typedef struct strbuf {
  char   *contents;
  size_t  length;  
} StringBuffer;

strbuf_reset将buf设置为cstr。成功返回buf,失败时为NULL。

StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
  if (!buf)  return NULL;      
  if (!cstr)  cstr = "";

  size_t len = strlen(cstr);
  if (len > buf->length) {
    char *new_contents = malloc(len + 1);
    if (!new_contents)  return NULL;
    free(buf->contents);
    buf->contents = new_contents;
  }
  memcpy(buf->contents, cstr, len + 1);
  buf->length = len;

  return buf;
}