【问题标题】:I think I am exceeding available memory for this process. Can someone take a look and verify?我认为我超出了此过程的可用内存。有人可以看看并验证吗?
【发布时间】:2019-06-21 17:00:51
【问题描述】:

当我不打开文件(180mb)时,我没有收到任何错误,但是当我打开文件时,我收到分段错误 11。我相当确定我超出了进程的内存。有人有什么建议吗?

我更改了参数。因此,如果 NUM_TRAIN = 10 而不是 60000,则不会出现分段错误。当 NUM_TRAIN = 60000,但我没有打开文件时,我也没有遇到分段错误。当 NUM_TRAIN = 60000 并打开文件时,出现分段错误。

#include <stdio.h>
#define NUM_TRAIN 60000
#define IMAGE_SIZE 784
#define TRAIN_IMAGES "mnist_train.csv"
int main()
{
  int arr[NUM_TRAIN][IMAGE_SIZE];
  int arr2[NUM_TRAIN];
  FILE* fTrain = fopen(TRAIN_IMAGES, "r");
  return 0;
}

我不希望出现分段错误,但我确实遇到了,特别是分段错误 11

【问题讨论】:

  • 使用 malloc 在堆而不是堆栈上分配数组。或者,在main()之外定义数组,将其放入全局内存区域。

标签: c file memory memory-management


【解决方案1】:

您正在堆栈上创建这些数组。与堆不同,它有严格的容量限制,不能扩展。 1-8MB 之间的限制很常见。

而是在堆上分配:

int **arr = malloc(sizeof(int *) * NUM_TRAIN);

for (int i=0; i < NUM_TRAIN; ++i)
{
   arr[i] = malloc(sizeof(int) * IMAGE_SIZE);
}

int 的二维数组实际上是指向int 数组的指针数组。

您应该在调用 malloc() 的过程中检查错误 - 这里省略。

【讨论】:

  • 不要将int **arr 用于简单的二维数组。它浪费空间和时间。使用int (*arr)[IMAGE_SIZE];arr = malloc(NUM_TRAIN * sizeof *arr);
  • int 的二维数组实际上并不是int 数组的指针数组。
  • @EricJ.: 很可能 OP 没有显示完整的代码,并且当文件未打开时,OP 也会省略将使用数组的代码,或者编译器能够推断出它们不使用,因此编译器优化了数组的创建。那么栈没有被使用,所以没有分段错误。
  • @marko:Eric J. 提出的问题不是堆栈溢出的原因,而是由于文件是否打开而导致堆栈溢出与否之间存在差异。
  • @JohnMancini:那么一个正确的问题和答案需要发布编译器和其他工具的完整版本信息以及用于编译和运行的确切命令,可能还有足够的信息来充分重现输入文件重现崩溃。如前所述,没有好的编译器会表现出报告的行为差异;无论文件是否打开,它都会保留数组(如果禁用了优化)并崩溃,或者删除数组(如果启用了优化)并且无论如何都不会崩溃。
【解决方案2】:

我解决了我的问题。基本上我用数组分配了太多的静态内存,所以我更改了代码以动态地将内存分配给堆。代码如下:

#include <stdio.h>
#include <stdlib.h>
#define NUM_TRAIN 60000
#define IMAGE_SIZE 784
#define TRAIN_IMAGES "mnist_train.csv"
int main()
{
  int** arr = (int**)malloc(sizeof(int*)*NUM_TRAIN);
  for (int i = 0; i < NUM_TRAIN; i++)
    arr[i] = (int*)malloc(sizeof(int)*IMAGE_SIZE);
  int* arr2 = (int*)malloc(sizeof(int)*NUM_TRAIN);
  FILE* fTrain = fopen(TRAIN_IMAGES, "r");
  return 0;
}

【讨论】:

  • 不要将int **arr 用于简单的二维数组。它浪费空间和时间。使用int (*arr)[IMAGE_SIZE];arr = malloc(NUM_TRAIN * sizeof *arr);
  • 关于“我分配了太多静态内存”:在函数内部,int arr[NUM_TRAIN][IMAGE_SIZE];不分配静态内存;它分配自动内存,这通常用堆栈来实现。
  • @EricPostpischil 你能解释一下为什么这样更节省空间和时间吗?
  • @JohnMancini,因为 Eric 的版本只需要一个 malloc() 调用(后来,只需要一个 free()),而不是其中的 NUM_TRAIN + 1,它只为需要的 @ 保留空间987654328@s,而不是额外的NUM_TRAIN 指针。此外,访问需要较少的间接访问,并且所有ints 肯定位于单个连续块中,这可能有助于更好的缓存局部性。总而言之,Eric 的版本要好很多
  • 更不用说这两种方法产生的对象虽然可以使用相同的索引语法访问,但实际上具有重要的不同类型。当您将它们作为函数参数传递时,差异会变得很明显。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 2021-10-13
  • 2017-04-22
  • 1970-01-01
相关资源
最近更新 更多