使用uint8_t双指针进行分段错误

时间:2016-01-17 17:06:09

标签: c segmentation-fault double-pointer uint8t

当影响[1] [0]的值时,我有一个分段错误,我认为我的mallocs是正确的但可能没有...

textbox1.TextChanged -= textbox1_TextChanged;
 textbox.Text = "some text";
 textbox1.TextChanged += textbox1_TextChanged;

2 个答案:

答案 0 :(得分:2)

请记住,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]

答案 1 :(得分:0)

  

我认为我的mallocs是正确的

他们不是。我们需要一张照片。你有两个独立的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个字节(xy个字节)保持为未初始化。

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

a[1][0] = ...在块B1中的偏移量4处使用4个字节作为指针。

问题是:这些字节中的前两个(xy字节)未初始化,后两个字节完全超出了已分配的块。所以你有两个错误的价格。

你可以清楚地看到例如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);