【问题标题】:segmentation fault with uint8_t double pointeruint8_t 双指针的分段错误
【发布时间】:2016-01-17 17:06:08
【问题描述】:

在影响 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
}

【问题讨论】:

    标签: c segmentation-fault double-pointer uint8t


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我认为我的 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 个字节(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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-02
        • 1970-01-01
        相关资源
        最近更新 更多