这个appender,realloc功能安全吗?

时间:2015-03-04 02:16:49

标签: c

刚刚从一些man文档中将这个函数放在一起,它需要一个char *并向它附加一个const char *,如果char *的大小太小,它会将它重新分配给更大的东西,最后将它附加到它。我用了c已经很久了,所以只需登记。

// append with realloc
int append(char *orig_str, const char *append_str) {
    int result = 0; // fail by default

    // is there enough space to append our data?
    int req_space = strlen(orig_str) + strlen(append_str);
    if (req_space > strlen(orig_str)) {
        // just reallocate enough + 4096
        int new_size = req_space;
        char *new_str = realloc(orig_str, req_space * sizeof(char));

        // resize success.. 
        if(new_str != NULL) {
            orig_str = new_str;
            result = 1; // success
        } else {
            // the resize failed.. 
            fprintf(stderr, "Couldn't reallocate memory\n");
        }
    } else {
        result = 1;
    }

    // finally, append the data
    if (result) {
        strncat(orig_str, append_str, strlen(append_str));
    }

    // return 0 if Ok
    return result;
}

2 个答案:

答案 0 :(得分:5)

这是不可用的,因为你永远不会告诉来电者你从realloc回来的内存。

您需要返回指针,或通过引用传递orig_str

另外(正如评论中所指出的)你需要realloc(orig_str, req_space + 1);来为空终止符留出空间。


您的代码有一些低效的逻辑,与此固定版本相比:

bool append(char **p_orig_str, const char *append_str)
{
    // no action required if appending an empty string
    if ( append_str[0] == 0 )
         return true;

    size_t orig_len = strlen(*p_orig_str);
    size_t req_space = orig_len + strlen(append_str) + 1;
    char *new_str = realloc(*p_orig_str, req_space);

    // resize success.. 
    if(new_str == NULL)
    {
        fprintf(stderr, "Couldn't reallocate memory\n");
        return false;
    }

    *p_orig_str = new_str;
    strcpy(new_str + orig_len, append_str);
    return true;
}

答案 1 :(得分:3)

这个逻辑没有任何意义:

// is there enough space to append our data?
int req_space = strlen(orig_str) + strlen(append_str);
if (req_space > strlen(orig_str)) {

只要append_str长度非零,您就必须重新分配。

主要问题是您尝试使用strlen跟踪缓冲区的大小。如果你的字符串是NUL终止的(因为它应该是),你感知的缓冲区大小总是与其中的数据完全相同,忽略任何额外的。

如果您想使用这样的缓冲区,您需要在单独的size_t中跟踪大小,或保留某种类似的描述符:

struct buffer {
    void    *buf;
    size_t   alloc_size;
    size_t   used_amt;    /* Omit if strings are NUL-terminated */
}