3

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

结构:

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;
 }
4

3 回答 3

7

你似乎不明白是做什么realloc的。

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

旧指针随后无效,如果您稍后尝试再次使用它时发生崩溃,这应该不足为奇。

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

于 2010-06-29T01:01:19.123 回答
1

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

如果 buf->contents 已经指向为 StringBuffer 分配的内存,尝试重新分配它会使内存系统陷入崩溃/挂起/损坏堆的情况,因为您将重新分配一个从未分配过的指针。

我认为结构应该如下所示,而不是尝试重新分配 buf-> 内容:

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

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

于 2010-06-29T01:02:24.833 回答
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;
}
于 2010-06-29T01:46:51.553 回答