2

将值影响到 a[1][0] 时出现分段错误,我认为我的 malloc 是正确的,但也许没有..

int main() {
    uint8_t **a;

    a = malloc(sizeof(uint8_t) * 6);
    *a = malloc(sizeof(uint8_t) * 2);

    a[0][0] = 1; // WORKS
    a[1][0] = 1; // DOES NOT WORK
}
4

2 回答 2

2

请记住,类型a是“指向uint8_t.

在您的第一个malloc中,您似乎想要a指向一个 6 数组uint8_t *。所以你sizeof错了;你应该这样做a = malloc(sizeof(uint8_t *) * 6)

现在a指向(的第一个元素)一个由 6 个指针组成的数组,这些指针是a[0]through a[5],每个指针都未初始化并且可能不指向任何有用的东西。

在第二个malloc中,您分配足够的内存来保存 2 uint8_t,并设置*a与 相同的a[0],以指向该内存。请注意a[1],...,a[5]仍然包含未初始化的指针。

所以访问a[0][0]很好,因为a[0]实际上确实指向有效内存。

a[1][0]不好,因为a[1]没有指向有效的内存。你从来没有用任何东西初始化a[1]

于 2016-01-17T20:17:25.417 回答
0

我认为我的 malloc 是正确的

他们不是。我们需要一张照片。您有两个单独的 malloc 块,一个大小为 6(假设sizeof(uint8_t)为 1);我们称它为 B1,尺寸为 2 之一(称它为 B2)。您还有两个指针:a指向第一个块,*a指向第二个块。

a --> [*a, x, y]
        |
        |-> [w, z]

假设您在 32 位系统上,并且sizeof(void*)是 4。

Line*a = malloc...将 B1 的前 4 个字节初始化为指向 B2,而 B1 的后 2 个字节(即x字节y)未初始化。

Linea[0][0] = ...将 B2 的第一个字节(w字节)初始化为 1。

Linea[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);
于 2016-01-17T20:29:03.090 回答