uint8_t 双指针的分段错误
segmentation fault with uint8_t double pointer
我在影响 a[1][0] 的值时遇到分段错误,我认为我的 mallocs 是正确的,但也许不正确..
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
}
记住 a
的类型是“指向 uint8_t
的指针。
在您的第一个 malloc
中,您似乎希望 a
指向 6 uint8_t *
的数组。所以你的 sizeof
是错误的;你应该做 a = malloc(sizeof(uint8_t *) * 6)
.
现在a
指向6个指针的数组(的第一个元素),从a[0]
到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]
。
i thought my mallocs were correct
他们不是。我们需要一张照片。您有两个单独的 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
字节)未初始化,后两个字节超出了分配块的大小。所以你有两个 bug 的价格一个。
你可以清楚地看到,例如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);
我在影响 a[1][0] 的值时遇到分段错误,我认为我的 mallocs 是正确的,但也许不正确..
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
}
记住 a
的类型是“指向 uint8_t
的指针。
在您的第一个 malloc
中,您似乎希望 a
指向 6 uint8_t *
的数组。所以你的 sizeof
是错误的;你应该做 a = malloc(sizeof(uint8_t *) * 6)
.
现在a
指向6个指针的数组(的第一个元素),从a[0]
到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]
。
i thought my mallocs were correct
他们不是。我们需要一张照片。您有两个单独的 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
字节)未初始化,后两个字节超出了分配块的大小。所以你有两个 bug 的价格一个。
你可以清楚地看到,例如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);