0

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

我的代码如下:

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 处中断(在:_CrtIsValidHeapPointer)

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

非常感谢提前

2012 年 8 月 26 日更新

我稍微修改了代码以适应人们的意见和建议。问题依然存在...

4

3 回答 3

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 消息表明您通过在给定的内存之外写入已经损坏了周围的字节。

于 2012-08-25T09:42:54.107 回答
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 都可以大大提高可读性。可读的代码更容易理解。

于 2012-08-25T09:47:37.930 回答
0

这是大错特错

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

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

(它也碰巧使用了奇怪的“逗号运算符”,它允许您有两个表达式,其中只有一个表达式。它评估并丢弃左侧的内容,并保留右侧的内容。这里不是很好! )

更好的分配将是

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

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

realloc 也有类似的问题,您为指针而不是整个对象分配空间。

于 2012-08-25T12:39:34.963 回答