c - 来自 realloc() 的奇怪行为

标签 c linux glibc

  • 编译器:GCC 4.7.2 (Debian 4.7.2-5)
  • 平台:Linux 3.2.0 x86 (Debian Wheezy)

编辑:请参阅下面的答案代码已更新并经过测试。它再次正确运行,感谢 WhozCraig。

我正在编写一个简单的头文件,其中包含动态操作宽字符串的函数。例如,我的 header 包含一个复制函数,可以在需要时扩展目标缓冲区。我正在编写的当前函数仅将提供的缓冲区的一部分复制到提供的目标缓冲区中。最初我使用的目标缓冲区对于我的测试用例来说已经足够大了,而且该函数完全没有问题。但我想测试我的 realloc() 逻辑,所以我将目标缓冲区的大小设置为 1,这样函数就必须 realloc() 目标缓冲区。但在我看来,realloc() 正在更改目标缓冲区内容的值。我已将错误追踪到第三次 realloc() 调用。这是我一直在使用的函数和测试用例。

#include <wchar.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>

#define DWS_DEF_SIZ 16

#define DWS_ENOMEM -1
#define DWS_EINVAL -2

int scpydws(wchar_t* *des, size_t *siz, int argc, wchar_t *src, size_t num, ...)
{   
    size_t i = 0;
    size_t j = 0;
    va_list argv;
    wchar_t *tmp = NULL;
    size_t x = 0;

    if(des == NULL) return DWS_EINVAL;
    if(siz == NULL) return DWS_EINVAL;
    if(*siz == 0 && *des != NULL) return DWS_EINVAL;

    if(*des == NULL)
    {
        if(*siz == 0)
        {
            if((*des = malloc(DWS_DEF_SIZ * sizeof(wchar_t))) == NULL) return DWS_ENOMEM;

            *siz = DWS_DEF_SIZ;
        }
        else if((*des = malloc(*siz * sizeof(wchar_t)) == NULL) return DWS_ENOMEM;
    }

    for(va_start(argv, num); argc > 0; argc--, src = va_arg(argv, wchar_t*), num = va_arg(argv, size_t))
    {
        if(src == NULL || src[0] == 0) continue;

        for(j = 0; j < num; j++, i++)
        {
            for(x = 0; x < i; x++) putwchar((*des)[x]);
            wprintf(L" | %i == %i\n", i, *siz - 1);

            if(i == *siz - 1)
            {
                if((tmp = realloc(*des, *siz * 2 * sizeof(wchar_t))) == NULL)
                {
                    va_end(argv);
                    return DWS_ENOMEM;
                }

                *siz *= 2;
                *des = tmp;
            }

            (*des)[i] = src[j];
        }
    }

    (*des)[i] = 0;
    va_end(argv);
    return 0;
}

int main()
{
    int ret = 0;
    size_t siz = 1;
    wchar_t *des = NULL;
    wchar_t src1[] = L"123456789";
    wchar_t src2[] = L"abcdefghijklmnopqrstuvwxyz";
    wchar_t src3[] = L"blahblah";

    //The syntax is fairly straight forward the numbers following the
    //buffers represent how many characters to copy into the destination buffer
    ret = scpydws(&des, &siz, 3, src1, 2, src2, 3, src3, wcslen(src3));
    wprintf(L"ret = %i\n", ret);

    return 0;
}

这是测试用例的输出。一切正常,直到第三次 realloc() “|”之前的字符表示函数操作期间的目标缓冲区。 “|”后面的内容表示目标缓冲区的函数索引变量(“==”左侧的整数)与目标缓冲区的最后一个有效索引(“==”右侧的整数)之间的比较,如果语句为真函数将重新分配()目标缓冲区。所以我的问题基本上是“Y”到底从哪里来的(见下文)?另外,正如我附注的那样,我在 Windows Vista SP3 系统上使用 MinGW-GCC(我不知道什么 MinGW-GCC 版本)编译了代码,而不是随机的“Y”字符,我从 realloc() 得到了一个 ENOMEM 错误,具有讽刺意味的是在第三次 realloc() 调用上,但我真的不在乎为什么会这样。

 | 0 == 0
1 | 1 == 1
12 | 2 == 3
12a | 3 == 3
12ab | 4 == 7
12abc | 5 == 7
12abcb | 6 == 7
12abcbl | 7 == 7 Note: The function realloc()s here
12abcYla | 8 == 15 Note: Notice how the 'b' changes to a 'Y'?
12abcYlah | 9 == 15
12abcYlahb | 10 == 15
12abcYlahbl | 11 == 15
12abcYlahbla | 12 == 15
ret = 0

最佳答案

malloc()realloc() 的大小参数需要乘以 sizeof(wchar_t)

我改变了这个:

*des = malloc(DWS_DEF_SIZ))

为此:

*des = malloc(DWS_DEF_SIZ * sizeof(wchar_t)))

还有这个:

tmp = realloc(*des, *siz * 2)

为此:

tmp = realloc(*des, *siz * 2 * sizeof(wchar_t))

感谢WhozCraig .

关于c - 来自 realloc() 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22737971/

相关文章:

c - 在C中初始化一个字符串

c++ - 指针转换真的打破了严格的别名吗?

c++ - 对于非常接近 1 的基数,std::pow() 非常慢

c++ - Fd 大于 1024 时 Select 和 FD_SET 的行为

c - 在 Linux Ubuntu 系统上,main 函数是由 _libc_start_main 函数调用的吗?

python - 在嵌入式 python 中创建新的 None 对象

linux - Indy 10.6 在具有管理员权限的 Linux 系统上使用 tcpserver 在客户端断开连接时抛出 Gtk-WARNING

linux - Linux 中两个文件重叠或分别用 file2 中的行替换 file1 中的行

c++ - 线程取消 (pthread) & C++

c - gtk+ 文本编辑器,打开 python 脚本中止,提示无效的 utf-8 文本