【问题标题】:What's wrong with this character buffer code?这个字符缓冲区代码有什么问题?
【发布时间】:2012-10-31 02:34:56
【问题描述】:

出于我保证存在的原因,我正在逐个字符地读取输入,如果一个字符符合某些条件,我会将其写入动态分配的缓冲区。此函数将指定字符添加到指定字符串的“结尾”。读取缓冲区时,我读取了第一个“大小”字符。

void append(char c, char *str, int size)
{
 if(size + 1 > strlen(str))
        str = (char*)realloc(str,sizeof(char)*(size + 1));
 str[size] = c;
}

此功能,经过多次迭代开发,产生了“损坏的双链表”、“双重释放或损坏”等错误。下面是应该如何使用 append 的示例:

// buffer is a string
// bufSize is the number of non-garbage characters at the beginning of buffer
char *buft = buffer;
int bufLoc=0;
while((buft-buffer)/sizeof(char) < bufSize)
    append(*(buft==),destination,bufLoc++);

它通常适用于一些看似任意数量的字符,然后因错误而中止。如果不清楚第二个代码 sn-p 在做什么,它只是从缓冲区复制到某个目标字符串。我知道有库方法可以解决这个问题,但有时我需要更好地控制复制的内容。

提前感谢您提供任何见解。我被难住了。

【问题讨论】:

    标签: c string buffer glibc realloc


    【解决方案1】:

    此函数不会将字符附加到缓冲区。

    void append(char c, char *str, int size)
    {
        if(size + 1 > strlen(str))
            str = realloc(str, size + 1);
        str[size] = c;
    }
    

    首先,strlen(str) 是什么?你可以说“这是str 的长度”,但这会省略一些非常重要的细节。它是如何计算长度的?简单——str 必须是 NUL 终止的,strlen 找到其中第一个 NUL 字节的偏移量。如果你的缓冲区末尾没有 NUL 字节,那么你就不能使用strlen 来查找它的长度。

    通常,您需要跟踪缓冲区的长度。为了减少重新分配的次数,请分别跟踪缓冲区大小和其中的数据量。

    struct buf {
        char *buf;
        size_t buflen;
        size_t bufalloc;
    };
    
    void buf_init(struct buf *b)
    {
        buf->buf = NULL;
        buf->buflen = 0;
        buf->bufalloc = 0;
    }
    
    void buf_append(struct buf *b, int c)
    {
        if (buf->buflen >= buf->bufalloc) {
            size_t newalloc = buf->bufalloc ? buf->bufalloc * 2 : 16;
            char *newbuf = realloc(buf->buf, newalloc);
            if (!newbuf)
                abort();
            buf->buf = newbuf;
            buf->bufalloc = newalloc;
        }
        buf->buf[buf->buflen++] = c;
    }
    

    另一个问题

    这段代码:

    str = realloc(str, size + 1);
    

    它只改变appendstr 的值——它不会改变调用函数中str 的值。函数参数是函数的本地参数,更改它们不会影响函数之外的任何内容。

    小问题

    这有点奇怪:

    // Weird
    x = (char*)realloc(str,sizeof(char)*(size + 1));
    

    (char *) 转换不仅是不必要的,而且它实际上可以掩盖错误——如果您忘记包含&lt;stdlib.h&gt;,转换将允许代码编译。无赖。

    根据定义,sizeof(char) 是 1。所以不要打扰。

    // Fixed
    x = realloc(str, size + 1);
    

    【讨论】:

      【解决方案2】:

      当您执行以下操作时:

      str = (char*)realloc(str,sizeof(char)*(size + 1));
      

      str 中的更改不会反映在调用函数中,换句话说,更改是函数本地的,因为指针是按值传递的。要解决此问题,您可以返回 str 的值:

      char * append(char c, char *str, int size)
      {
       if(size + 1 > strlen(str))
              str = (char*)realloc(str,sizeof(char)*(size + 1));
       str[size] = c;
      
       return str;
      }
      

      或者你可以通过地址传递指针:

      void append(char c, char **str, int size)
      {
       if(size + 1 > strlen(str))
              *str = (char*)realloc(*str,sizeof(char)*(size + 1));
       (*str)[size] = c;
      }
      

      【讨论】:

      • 调用strlen也有问题。
      猜你喜欢
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-16
      • 2012-08-07
      • 2014-08-29
      • 2013-06-05
      相关资源
      最近更新 更多