代码之家  ›  专栏  ›  技术社区  ›  aurel_lab

uint8t双指针的分段错误

  •  3
  • aurel_lab  · 技术社区  · 10 年前

    当影响[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
    }
    
    2 回复  |  直到 10 年前
        1
  •  2
  •   Nate Eldredge    10 年前

    请记住 a 是“指针指向 uint8_t .

    在你的第一个 malloc ,看起来像你想要的 一 指向6的数组 uint8_t * .所以你的 sizeof 是错误的;你应该这么做 a = malloc(sizeof(uint8_t *) * 6) .

    现在 一 指向由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] 什么都可以。

        2
  •  0
  •   Employed Russian    10 年前

    我认为我的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个字节( x , y 字节)未初始化。

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

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

    问题是:这些字节中的前两个( x(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);