这个字符缓冲区代码有什么问题?

时间:2012-11-11 11:26:56

标签: c string buffer glibc realloc

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

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++);

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

提前感谢任何见解。我很难过。

2 个答案:

答案 0 :(得分:4)

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

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

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

轻微的狡辩

这有点奇怪:

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

(char *)强制转换不仅是不必要的,而且它实际上可以掩盖错误 - 如果您忘记包含<stdlib.h>,则强制转换将允许代码进行编译。长号。

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

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

答案 1 :(得分:0)

当你这样做时:

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