【问题标题】:why I am getting segmentation fault with scanf at large inputs为什么我在大输入时遇到 scanf 分段错误
【发布时间】:2015-03-15 09:20:30
【问题描述】:

我已经编写了 c 代码来合并排序输入数组 我尝试了 2 3 5 10 100 1000 10,000 和 1,000,000 的代码 除了 10,000 和 1,000,000 之外,它在所有情况下都可以正常工作 调试后发现错误在scanf()代码内

Program received signal SIGSEGV, Segmentation fault.
0x00000000004006a7 in main () at merge.c:10
10          scanf("%i",&array[i]);

但就我而言,代码完全正确

 int len;
        scanf("%i",&len);
        int array[len];
        for(int i=0; i<len;i++)
        {
                scanf("%i",&array[i]);
        }

如果您需要完整的代码来说明,这里是

#include <stdio.h>
void mergesort(int* list , int len);
int main()
{
        int len;
        scanf("%i",&len);
        int array[len];
        for(int i=0; i<len;i++)
        {
                scanf("%i",&array[i]);
        }
        mergesort(array,len);
        for(int i=0; i<len;i++) printf("%i\n",array[i]);
        printf("\b");
}
void mergesort (int* list, int len)
{
        if(len == 1) return;
        int i = len/2, j = len-i;
        int list1[i], list2[j];
        for(int k=0;k<i;k++)
        {
                list1[k]= list[k];
                list2[k]= list[i+k];
        }
        if(len%2!=0) list2[j-1] = list[len-1];
        mergesort(list1 , i);
        mergesort(list2 , j);
        int k=0,l=0;
        // k represent counter over elements in list1
        // l represent counter over elements in list2
        // k+l represent counte over total elements in list
        while(k+l!=len)
        {
                if(k==i)
                {
                        for(;l<j;l++) list[k+l] = list2[l];
                        return;
                }
                else if (l==j)
                {
                        for(;k<i;k++) list[k+l] = list1[k];
                }
                else if(list1[k]<list2[l])
                {
                        list[k+l]=list1[k];
                        k++;
                }
                else if(list1[k]>list2[l])
                {
                        list[k+l] = list2[l];
                        l++;
                }
                else
                {
                //handles dublication
                list[k+l] = list1[k];
                k++;
                list[k+l] = list[l];
                l++;
                }
        }
}
EDIT:

如果您认为问题平台依赖我使用 ubuntu 14.04 和 gnu c 编译器 4.8.2,我用标志 -std=c99 -Wall 编译代码 并且没有错误和警告

【问题讨论】:

  • int array[len]; 不是C
  • 声明有什么问题
  • @Rohan:可变长度数组 (VLA) 在 C99 中,所以不是这样。 (否则会是编译错误。)
  • 堆栈溢出?对于递归函数来说,这是一个很大的堆栈空间。如果您对数组使用 malloc/free 是否有效?
  • 我认为不是递归函数的原因,因为在调用mergesort()之前收到了分段错误信号

标签: c arrays sorting merge scanf


【解决方案1】:

合并排序会占用大量内存,并且您在 c 程序员调用的堆栈 (int list1[i], list2[j];) 中分配了额外的内存。实际上堆栈中的空间很小。对较大的值反复执行此操作超出了限制。

您必须改用分配 - 动态分配。堆有大量可用于分配的内存,并且用于大型数组以及其他用途。你这样做:

//C example with malloc, ALWAYS use sizeof
int *array = (int*) malloc( length * sizeof(int));

//C++ way
int *array = new int[length];

但内存在程序结束后仍然被分配,除非你释放它。在这种情况下,这可能是一个问题。 确保在不再需要时取消分配。

//C way
free(array);

//C++ way for arrays
delete[] array;

//C++ way for single heap values
delete value;

这是正确的方式,所以你应该习惯它,因为你将来非常需要动态分配。

【讨论】:

    猜你喜欢
    • 2020-08-03
    • 2016-05-03
    • 1970-01-01
    • 2020-08-03
    • 2013-01-23
    • 1970-01-01
    相关资源
    最近更新 更多