对于指向数组的指针,realloc失败(在C中)

时间:2012-08-25 09:36:30

标签: c memory heap corruption realloc

我正在尝试动态地为(基本上是)一个二维chars数组分配内存 - 即 - 一个字符串数组。

我的代码如下:

typedef char LineType[MAX_CHARS+1];
LineType* lines;

int c = 0;
int N = 2;

lines = (LineType *) malloc (N * sizeof( LineType) );
do { 
    if (c > N ) {
        N *=2;
        lines = (LineType*) realloc (lines, N * sizeof( LineType));
    }

    .
    .
    .
    c++;

} while ( . . . )

这编译很好但在运行时失败,发出警告可能的HEAP CORRUPTION并在dbgheap.c中断(in:_CrtIsValidHeapPointer)

我做错了什么?我认为这可能是由于数据结构中混合了固定/动态维度......但是,对于字符串的数组(不同大小)声明然后动态分配(和重新分配)内存的最佳方法是什么?每个都是固定的大小)?

提前多多感谢

更新26/8/2012

我稍微更改了代码,将其调整为人们的意见和建议。问题仍然存在......

3 个答案:

答案 0 :(得分:2)

假设c用于索引lines,您需要测试c >= N,而不是c > N

另外,我建议使用typedef使代码更具可读性。我也会避免冗余分配代码:

typedef char fixed_string[MAX_CHARS + 1];

int c = 0;
int N = 0;
fixed_string *lines = NULL;

do {
    if (c >= N ) {
        N = N ? 2*N : 2;
        lines = (fixed_string*) realloc (lines, N * sizeof(fixed_string));
    }
    ⋮
    c++;
} while (…);

另外,使用2的增长因子时要小心。它留下了永远不会被同一个数组重用的漏洞。因子1.5(3*N/2)更安全。

编辑:我从其他评论中注意到您在重新分配时遇到崩溃。这与写入数组末尾的结果一致。调试内存分配器将使用特殊字节填充紧接在已分配内存块周围的空间,并检查下次使用该内存块执行某些操作时是否保留这些字节。 HEAP CORRUPTION消息表示您通过在给定的内存外写入来破坏周围的字节。

答案 1 :(得分:0)

让事情更具可读性:

而不是

char (*lines) [MAX_CHARS +1];

做一个

typedef char LineType[MAX_CHARS+1];
LineType* lines;

以类似的方式,

lines = (char (*) [MAX_CHARS +1]) calloc (N, sizeof( char (*) [MAX_CHARS +1]));
...
lines = (char (*) [MAX_CHARS + 1]) realloc (lines, N * sizeof( char (*) [MAX_CHARS +1]));

变成

lines = malloc(N*sizeof(LineType));
...
lines = realloc(lines, N * sizeof(LineType));

注意:我用malloc替换了calloc,因为我从不使用calloc,所以我不确定它是否尝试使用对齐技巧。

无论哪种方式,小型typedef都可以提高可读性。可读代码更容易实现。

答案 2 :(得分:0)

这是非常错误的

lines = (LineType *) malloc (N, sizeof( LineType *) );

因为它只为一个指针sizeof(LineType*)而不是多个字符串分配空间。

(它也恰好使用奇数"comma operator",它允许你有两个表达式,只有一个是预期的。它评估并丢弃左侧的内容,并保留右侧的内容。这里非常好!)

更好的分配是

lines = malloc(N * sizeof(LineType));

我们为类型为LineType的N个对象分配空间。

realloc存在类似的问题,您可以为指针而不是整个对象分配空间。