我认为我的 malloc 是正确的
他们不是。我们需要一张照片。您有两个单独的 malloc 块,一个大小为 6(假设 sizeof(uint8_t) 为 1);我们称它为 B1,尺寸为 2 之一(称它为 B2)。您还有两个指针:a 指向第一个块,*a 指向第二个块。
a --> [*a, x, y]
|
|-> [w, z]
假设您在 32 位系统上,sizeof(void*) 是 4。
*a = malloc... 行将 B1 的前 4 个字节初始化为指向 B2,而 B1 的后 2 个字节(x、y 字节)未初始化。
a[0][0] = ... 行将 B2 的第一个字节(w 字节)初始化为 1。
a[1][0] = ... 行使用块 B1 中偏移 4 处的 4 个字节作为指针。
问题在于:这些字节中的前两个字节(x、y 字节)未初始化,而后两个字节完全超出了分配的块。所以你有两个错误的价格。
你可以清楚地看到,例如valgrind 输出:
==9576== Invalid read of size 4
==9576== at 0x804845A: main (/tmp/t.c:12)
==9576== Address 0x420005c is 4 bytes inside a block of size 6 alloc'd
==9576== at 0x402DBFA: malloc (valgrind/coregrind/m_replacemalloc/vg_replace_malloc.c:270)
==9576== by 0x8048431: main (/tmp/t.c:8)
==9576==
==9576== Use of uninitialised value of size 4
==9576== at 0x804845C: main (/tmp/t.c:12)
==9576==
==9576== Invalid write of size 1
==9576== at 0x804845C: main (/tmp/t.c:12)
==9576== Address 0x0 is not stack'd, malloc'd or (recently) free'd
现在,不清楚您想要分配的矩阵大小是多少(6 是从哪里来的?)。
假设您想创建一个动态分配的 MxN 数组,那么正确的代码是:
uint8_t **a;
a = malloc(M * sizeof(a[0]));
for (j = 0; j < M; ++j)
a[j] = malloc(N * sizeof(a[0][0]));
// Now all M by N elements are accessible:
for (j = 0; j < M; ++j)
for (k = 0; k < N; ++k)
a[j][k] = 1;
// cleanup.
for (j = 0; j < M; ++j)
free(a[j]);
free(a);