该程序中的分段错误是啥

Posted

技术标签:

【中文标题】该程序中的分段错误是啥【英文标题】:what is the segmentation fault in this program该程序中的分段错误是什么 【发布时间】:2017-03-12 04:17:38 【问题描述】:
 #include<stdio.h>
 #include <stdlib.h>
 int main()
 
         int n,small=0,large=0,s,l,temp;
         printf("this should work");
         scanf("%d",&n);
          //   printf("%d",n);//
         int a[n];
        for(int i=0;i<n;i++)
             
              scanf("%d",&a[i]);
              
             /*    for(int i=0;i<n;i++)
                          printf("%d",a[i]);*/
        small=a[0];
        large=a[n-1];
        for(int i=0;i<n;i++)
        
               if(a[i]<small && i!=0)
                 
                       small=a[i];
                       s=i;
                
                if(a[i]>large && i!=n-1)
                 
                        large=a[i];
                        l=i;
                 
        
        temp=a[s];
        a[s]=a[l];
        a[l]=a[s];
        for(int i=0;i<n;i++)
              printf("%d ",a[i]);
         return 0;
  

这是一个交换数组中最大和最小数字并打印新数组的简单程序。 当我试图运行这个程序时,我遇到了分段错误。 通常,当我们尝试访问超出范围的内存位置时会发生分段错误。 所以我添加了 printf 语句来找出错误在哪里。 但是没有执行任何打印语句。这里有什么错误?

【问题讨论】:

1) small=a[0]; large=a[n-1]; --> small=a[0]; s=0; large=a[n-1]; l=n-1; 2) a[l]=a[s]; --> a[l]=temp; 您可以使用C调试器gdb来查找出现分段错误的行。 请将编译器的警告调到最大,这样您就可以轻松获取可能的问题点的信息,就像这里的那些 【参考方案1】:

一个问题是你实际上并没有将sl 设置为任何东西,除非你找到一个小于/大于当前元素的元素。

这意味着(例如),如果第一个元素是最小的,s 将被设置为任意值,并且尝试使用它来索引数组可能会出现问题。

要解决这个问题,在哪里设置smalllarge,您还应该设置:

s = 0;
l = n - 1;

另外,你的交换码是错误的,应该是:

temp = a[s];
a[s] = a[l];
a[l] = temp;

【讨论】:

【参考方案2】:

您应该将sl 初始化为某个值,因为当if 条件不起作用时,它们的值将保持未初始化的垃圾值。因此,a[l]a[s] 将不起作用,因为这些索引是未定义的值。这就是为什么您会得到segmentation fault 的原因,因为您正在访问数组的未定义区域。

因此,请使用 s=0,l=0 等数组范围内的随机值来初始化变量,或者您可以添加一些标志来检查条件是否有效。

if (l != 0 && s != 0) 
    temp=a[s];
    a[s]=a[l];
    a[l]=a[s];

另外,我认为您在最后一行 a[l]=temp 而不是 a[l]=a[s] 中交换了值。

ideone link

【讨论】:

【参考方案3】:

你不能声明一个基于动态大小的数组,除非编译器支持它,即使那样它通常也是不可移植的。

int a[n]

你实际上需要使用 malloc 或 calloc。

int *a;

a = (int *)malloc(n * sizeof(int));或 a = (int *)calloc(n, sizeof(int));

【讨论】:

如果编译器支持可变长度数组,则可以。也永远不要转换 malloc 的返回值。这不是问题的答案 显式强制转换不是必需的,但有助于提高代码的可读性并防止将来由于 'a' 类型的更改而产生的副作用。可变长度数组不是标准选项,需要明确启用。 不,它隐藏了问题,增加了混乱,通常被认为是不好的做法。 ***.com/a/605858/1806780 该链接建议使用取消引用的指针变量的类型。恕我直言,如果您更改类型并且没有正确处理更改,这也是一个问题。与未知的副作用相比,混乱更令人担忧。

以上是关于该程序中的分段错误是啥的主要内容,如果未能解决你的问题,请参考以下文章

是啥导致发生分段错误?

分段错误错误(信号名称:SIGSEGV)的原因是啥,我将如何找到/修复它?

是啥导致了这种分段错误?

我的 Vigenere 加密程序中的分段错误

多线程程序中的分段错误和 gdb 回溯信息不完整

使用 C (Ubuntu) 进行套接字编程中的分段错误