【问题标题】:Accessing array declared by malloc访问 malloc 声明的数组
【发布时间】:2012-09-26 09:35:30
【问题描述】:

我正在处理一项任务(详情见another question)。作为其中的一部分,我正在增加数组的大小。并发现当我尝试初始化一个数组时:

int arr[2097152]; // 8MB

我遇到了分段错误...我认为是因为我试图声明一个太大的数组?然后我发现解决这个问题的方法是使用malloc。但是对 C 来说是新手(主要使用 JavaScript/Python/Java ...)。我对指针和东西感到非常困惑......

我已经声明了一个 8MB 的数组:

int *arr = malloc (MBs * 1024 * 1024 / sizeof(int)); // MBs = 8

但是现在......我如何访问它,或写入它?当我像arr 一样使用它时,我得到了地址,如果我使用*arr,我得到了第一个元素?

【问题讨论】:

  • 来自 JS/Python 的你应该了解堆栈和堆内存分配之间的区别。
  • malloc 将字节数作为参数,所以它只是malloc(MBs * 1024 * 1024);
  • 除了提到 malloc 以及堆栈和堆之间的区别的答案之外,请记住,您也必须自己释放这个数组。如果你只在你的程序中创建了一次,你可能会逃脱,因为当你的程序终止时它会自动释放。但是,如果您在某些函数中重复执行此分配,并认为一旦超出范围就会破坏数组,那将是一场灾难

标签: c pointers


【解决方案1】:

arr[index] 一样使用它,就像它被声明为一个数组一样。在 C 中,符号 x[y] 完全等同于 *(x + y)。这适用于数组,因为数组名称被转换为指向其第一个元素的指针。

int *arr = malloc (MBs * 1024 * 1024 / sizeof(int));

这不是一个好方法(并且不会使其达到您想要的大小),因为您手头没有足够的元素数量。您应该根据元素的数量来声明它,例如,

#define ARR_LENGTH 2097152
int *arr = malloc (ARR_LENGTH * sizeof *arr);

您需要乘以元素大小,因为 malloc 的参数是字节数。

【讨论】:

  • 为什么这不是一个好方法?是因为MBs * 1024 * 1024 / sizeof(int) 可能会给出小数或其他什么?我想你的意思是sizeof(int)? ...哦,“我没有数组的大小”,是因为我不能再通过sizeof(arr)/sizeof(int) 来查找数组的大小?
  • @JiewMeng 是的,你不能这样做,但你需要知道元素的数量。我的意思是我写的sizeof *arr,它避免了对类型的依赖。如果您稍后更改类型,您的程序会出现错误并且可能会随机崩溃。如果更改变量名,只会出现语法错误。相信我,我有 35 年的 C 语言经验,这是最佳实践。
  • @JiewMeng 使用sizeof *arr 的另一个原因是它在所有 malloc 调用中始终相同,而 OTOH 类型可能很复杂或容易出现拼写错误,弄错可能是一场灾难。假设,例如,你有一个指向字符串的指针数组,你写成char** arr = malloc(ARR_SIZE * sizeof(char)) ...哎呀,bug city,因为你没有分配足够的内存。
【解决方案2】:

我认为是因为我试图声明一个太大的数组?

是的,确实。您很可能在函数中执行此操作。其中阵列是在堆栈上的本地存储上创建的,通常堆栈不会大到足以满足这种大尺寸的需求。
通常的解决方案是使用动态内存。

我如何访问它或写入它?当我像arr 这样使用它时,我得到了地址,如果我使用*arr,我得到第一个元素?

您可以通过使用[] 运算符以与使用数组类似的方式访问它。

注意,

arr[i] == i[arr] == *(arr + i) == *(i + arr)

所以,

arr[0] ---> Gives you first element
arr[1] ---> Gives you Second element
and so on...

请注意,数组的名称有时会衰减为指向其第一个元素的指针,但数组和指针并不相同!

好读:

How do I use arrays in C++?

【讨论】:

    【解决方案3】:

    是的,您可以像使用 ARRAY 一样使用它。

    int *arr = malloc (MBs * 1024 * 1024) ;
    arr[0] = 1 ;
    arr[6] = 675 ;
    etc. ;
    

    *arr = arr[0] ; \第一个元素

    【讨论】:

      【解决方案4】:

      符号a[i]*(a + i) 相同(因此也与i[a] 相同,因为加法是可交换的)。由于指针算法和数组到指针的衰减,您可以将这种语法用于数组和指向数组元素的指针:

      int a[10];
      int * b = a + 4;
      int * c = malloc(sizeof(int) * 100);
      
      a[2];   // third element of a
      b[1];   // sixth element of a
      c[3];   // fourth element of the array starting at c
      
      free(c);  // don't forget to clean up!
      

      关于您的第一个问题:自动变量的可用空间确实有限。溢出这个空间被称为...堆栈溢出。

      【讨论】:

        【解决方案5】:

        您还可以尝试将大数组作为静态变量放在堆栈区域之外。可能你不会再有段错误了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-02-20
          • 1970-01-01
          • 1970-01-01
          • 2014-05-22
          • 2021-03-29
          • 1970-01-01
          • 1970-01-01
          • 2018-01-21
          相关资源
          最近更新 更多