C 中的 realloc() 问题。总是挂起,但编译正常

发布于 2024-09-07 05:17:30 字数 2136 浏览 7 评论 0原文

我在使用一个旨在成为字符串缓冲区的程序时遇到了一些麻烦,特别是此函数旨在使用字符串 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;
 }

I'm having some trouble with a program that is intended to be a String buffer, specifically this function is intended to reset the buffer with the string cstr. If cstr is null then the content needs to be reset to an empty char '\0'. It always hangs at the second set of realloc where it's resizing buf->contents I have no clue why that is. Any help would be awesome.

The struct:

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

It is called from

strbuf_reset(sb, NULL)

Here is the strbuf_reset function that is having the problem.

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

With what I believe to be the suggested changes...

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

意中人 2024-09-14 05:17:30

您似乎不明白 realloc 的作用。

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

那么旧指针无效,如果稍后尝试再次使用它时发生崩溃,也不足为奇。

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

You don't seem to understand what realloc does.

The way you should be thinking about it (at least as far as enlarging goes), is that it allocates a new buffer, copies the old data into it, and then frees the old buffer.

The old pointer is then invalid and it should not be suprising if you get crashes when you try and use it again later.

You should be assigning the returned value back to the old pointer immediately, so it still points at valid data.

三寸金莲 2024-09-14 05:17:30

由于您要覆盖 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;
}

Since you are going to overwrite StringBuffer's contents, using realloc makes no sense. It will not save you any memory allocation but instead will copy old data you intent to overwrite anyway. Use normal malloc and free.

With your original structure

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

strbuf_reset sets buf to cstr. On success returns buf, on failure 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;
}
ζ澈沫 2024-09-14 05:17:30

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

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

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

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

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

You are allocating extra space for the string in the StringBuffer. I just assumed buf->contents is supposed to point into that extra allocated space. If this is not true then why is the extra space allocated in the StringBuffer?

If buf->contents already points into memory that was allocated for StringBuffer, attempting to realloc it will throw the memory system into a crash/hang/corrupt heap situation, because you would be realloc'ing a pointer that was never allocated.

Instead of attempting to realloc buf->contents, I think the structure should look like:

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

Then instead of reallocing buf->contents you just copy the string into there and the realloc for StringBuffer takes care of all the memory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文