分段错误:在 Mac 上为 11,但在 Linux 上没有,同时在 C 中创建数组

Posted

技术标签:

【中文标题】分段错误:在 Mac 上为 11,但在 Linux 上没有,同时在 C 中创建数组【英文标题】:Segmentation fault: 11 on mac but not on linux while creating an array in C 【发布时间】:2019-01-14 20:03:08 【问题描述】:

您好,我最近开始测试 QuickSort。我编写了一个程序,该程序使用用户输入的大小制作数组并用随机数填充它,然后使用快速排序对其进行排序。现在这是我的问题。在只有 4gb 内存的 linux 机器上,我可以在计算机无法使用之前制作最大 10^8 的数组。在我的 8gb 内存的 mac 上,我只能创建一个大小为 10^6 的数组。如果我尝试制作一个大小为 10^7 或更大的数组,则会出现分段错误。是操作系统的一些硬限制,可以更改吗? 这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int FindPivot(int i, int j);
void PrintTable(int* table, int size);
void NextThing(int* table, int size);
void QuickSort(int* table, int i, int j);

void RandomizeTable (int* table, int size)  

  int i;
  for (i = 0; i < size; i++) 
    table[i] = -10000 + rand() % (10000+1-(-10000));
    //printf("%d\t", table[i]);
  
  printf("\n");
  NextThing(table, size);


void NextThing(int* table, int size)  
  printf("Sorting the table...\n");
  clock_t x = clock();
  QuickSort(table, 0, size - 1);
  clock_t y= clock();
  printf("Time it took : %fs\n", ((double)(y - x))/CLOCKS_PER_SEC);

  //Second sorting of the table, just to see how long does it take for quicksort to sort an already sorted table
  printf("Sorting the table...\n");
  clock_t x2 = clock();
  QuickSort(table, 0, size - 1);
  clock_t y2= clock();
  printf("Time it took : %fs\n", ((double)(y2 - x2))/CLOCKS_PER_SEC);


  exit(0);


void Swap(int* table, int i, int j) 
  int temp;
  temp = table[i];
  table[i] = table[j];
  table[j] = temp;


int Partition(int* table, int i, int j) 
  int p, q, key; 

  p = FindPivot(i, j);
  key = table[p];

  Swap(table, i, p);

  for (p = i, q = i + 1; q <= j; q++)
    if (table[q] < key) 
      p++;
      Swap(table, p, q);
    
    Swap(table, i, p);
  return p;


void QuickSort(int* table, int i, int j) 
  int p;
  if (i < j) 
    p = Partition(table, i, j);
    QuickSort(table, i, p - 1);
    QuickSort(table, p + 1, j);
  
//QuickSort 

void PrintTable(int* table, int size) 
    int i;
    for (i = 0; i < size; i++)
        printf("%d", table[i]);
    printf("\n");   


int FindPivot(int i, int j) 
  int pivot;
  /*pivot = i + rand() % (j + 1 - i); */ //Method I randomizing pivot
  pivot = (i + j) / 2; //Method II arithmetic avarage
  return pivot;




int main ()    

    time_t t;
    srand((unsigned) time(&t));

  int n;
  printf("Array size:");
  scanf("%d", &n);  
  int tab[n];     //Here is where error occurs if array size is > 10^6


  RandomizeTable(tab, n);


我几乎可以肯定,制作这样大小的数组是有问题的。我试过用 printf 调试代码。如果是在创建数组之前(在 main() 中)它会打印文本,如果我在之后放置它就不会打印它。

【问题讨论】:

您的符号time_t t; srand((unsigned) time(&amp;t)); 很冗长:您可以使用srand(time(0));,或者,如果您坚持强制转换,则使用srand((unsigned)time(0));time() 函数对空指针作为其参数感到满意。 在大多数 Unix 系统上,您最多可以在堆栈上创建大约 8 MiB。不过,您通常应该在达到那个点之前很久就开始使用动态内存分配——开始担心是否在堆栈上创建了 1 MiB 的数据(如果只是因为在 Windows 上限制通常是 1 MiB——但也因为你可能没有想要在使用递归算法时吃掉所有的堆栈)。 在 linux 下,内存使用有一定的限制,可能是硬的或软的(取决于内核构建)。其中之一是“堆栈大小”。在 csh 中,您可以使用 limit 命令来检查和设置这些(如果它们是软的)。 mac 可能有类似的东西。 【参考方案1】:

假设您使用的是 C99,它可能是特定于实现的(但可能不是),其中任何对象的最大大小受 SIZE_MAX 限制,来自this post,这意味着最小 (理论上)可能小于 10^6 (1,000,000) 字节。

如果这是问题,您可以使用类似的方法进行检查

size_t max_size = (size_t)-1;

来自here。

否则,另一个帖子是你最好的选择——如果你不能在堆栈上实现它,使用malloc 可以在堆中分配它。

int *tab = malloc(n*sizeof(int));

这将在堆中分配 (n * sizeof(int in bytes)) 个字节,并且应该可以工作。

请注意,如果您以这种方式分配内存,则需要手动删除它,因此您应该在完成后调用free。

free(tab)

【讨论】:

动态分配就是答案。 在大多数系统上,SIZE_MAX 是 2³²-1(对于 32 位)和 2⁶⁴-1(对于 64 位)。虽然理论上SIZE_MAX 可能小到 65535 (2¹⁶-1),但在任何台式机或服务器系统上,这比实际情况更具理论性——如果限制那么小,您将使用 8 位微处理器。跨度> 无论 C 的版本如何,限制往往是相同的。但是,在 C90 中,SIZE_MAX 不是强制宏;它被添加到 C99 中(但也在 C11 和 C18 中)。

以上是关于分段错误:在 Mac 上为 11,但在 Linux 上没有,同时在 C 中创建数组的主要内容,如果未能解决你的问题,请参考以下文章

C++ 服务器 Linux 机器上的分段错误 - 适用于 Mac

linux (g++) 上的分段错误,但 Mac OS 上没有。?

ejabber 的 erl 文件在 mac os 10.7.5 上运行时给出错误“分段错误:11”

Python 3.4在生成一些 - 但不是全部 - 具有分段错误11的Cartopy地图时崩溃

在 Mac OS X Sierra 上为 Django Python 安装 mysqlclient

PyQt4 setItemDelegateForRow 导致分段错误