如何删除我的 C++ 代码中的分段错误?

Posted

技术标签:

【中文标题】如何删除我的 C++ 代码中的分段错误?【英文标题】:How to remove Segmentation Fault in My C++ code? 【发布时间】:2021-09-12 17:20:12 【问题描述】:

我编写了一个 C++ 函数,它以数组及其大小作为参数并执行某些操作。当我尝试运行此代码时,它显示分段错误。有人可以告诉我为什么此代码显示分段错误以及如何删除它?

void rearrange(long long *arr, int n) 
 
    long long temp[n];
    int max = n-1;
    int min = 0;
    for(int i=0;i<n;i++)
        if(i%2 == 0)
            temp[i] = arr[max];
            max--;
        
        else
            temp[i] = arr[min];
            min++;
        
    
    
    for(int i=0;i<n;i++)
        arr[i] = temp[i];
    

【问题讨论】:

你是怎么调用这个函数的? 您尝试调试代码吗?long long temp[n]; 不是有效的 c++。 您是否尝试编译代码,long long temp[n] 应该会报错。查看具有运行时确定大小的数组的 std::vector 。好消息是您可以通过显式引用传递它们,例如重新排列(std::vector& arr)。如果您在编译时确实知道大小,则可以使用重新排列(std::array& arr). @PKramer 这是 g++ 编译器扩展。 @Eugene Meh,那不是标准的 C++。 【参考方案1】:

我试图这样调用你的函数(不改变任何内容):

void rearrange(long long *arr, int n) 

    long long temp[n];
    int max = n - 1;
    int min = 0;
    for(int i = 0;i < n;i++) 
        if(i%2 == 0) 
            temp[i] = arr[max];
            max--;
         else 
            temp[i] = arr[min];
            min++;
        
    
    for(int i = 0;i < n;i++) 
        arr[i] = temp[i];
    


int main()

    const int n = 10;
    long long arr[] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
    rearrange(arr, n);
    return 0;

编译器g++ 9.3.0 没有显示错误,也没有引发SIGSEG 信号。

但是!

你的功能有弱点。现代 C++ 编译器允许您像以前那样声明数组:

long long temp[n];

弱点在于变量n 的值在编译期间是未知的。这是一种糟糕的 C++ 方式。最好这样做(如果您选择 C ​​样式的数组):

void rearrange(long long *arr, int n) 

    long long *temp = new long long[n];
    ...
    ...
    ...
    delete temp;

此外,您可能调用了一个函数并传递给它一个指向随机内存位置的指针arr,即没有为数组分配内存。例如,如果你用这样一个未初始化的指针调用你的函数,操作系统会发起一个信号SIGSEG(Segmentation Fault):

int main()

    const int n = 10;
    long long *arr;    // pointing to any (unknown) memory cell
    rearrange(arr, n);
    return 0;

但在这种情况下,g++ 显示警告消息:“arr”在此函数(main)中未初始化

【讨论】:

更好的方法是使用std::vector&lt;long long&gt;push_back 的值。 @Thomas Matthews,你能解释一下为什么它是解决这个问题的更好方法吗?当然,标准 C++ 库功能强大,提供了更多高级编程机会。我们可以在这个问题中使用矢量。但是我确信这个问题的作者是一个初学者,因为他已经提出了这个问题。那么向初学者解释什么更容易:通常的指针 - 这是语言的一部分,不需要任何库 - 或许多标准库容器之一?在我看来,我已经展示了最接近作者风格的解决方案之一。 @V.Fedulov RAII 仅举一个。总的来说,我同意Kate Gregory。 @V.Fedulov: 1) 内存管理(用于扩展)已经实现,并经过测试。您不必浪费时间进行开发和调试。 2)std::vector 有一个size 方法。当您将 std::vector 传递给函数时,您始终可以获得大小。数组需要传递数组的开头和容量(甚至可能是元素的数量)。 3) 与其他函数一起传递的语法更容易。 4) std::vector 删除它分配的所有内存。使用动态分配的数组,必须记住何时删除内存。这够了吗? 是的,但我要求解释为什么 vector 是这个特定问题的最佳解决方案。显然,作者不再对这个问题感兴趣。我只是想说明他不使用 std 库时遇到的错误的性质。【参考方案2】:

问题很可能是数组索引越界。如果n 大于数组的大小或为负数,就会发生这种情况。

一种解决方案是使用std::vector&lt;long long&gt; &amp;arr 而不是long long *arr,这样可以使用size() 函数而不是依赖n 来等于数组大小。

【讨论】:

【参考方案3】:

首先,您不能创建数组指针。数组总是通过引用传递的。按照这段代码,

void rearrange(long long arr[], int n)
// do some thing

【讨论】:

我的建议是尽可能停止使用“C”风格的数组,改用std::array/std::vector。 请注意,此函数与 OP 的签名完全相同。 你当然可以让数组衰减为指针;无论哪种方式,它在逻辑上都是等价的。

以上是关于如何删除我的 C++ 代码中的分段错误?的主要内容,如果未能解决你的问题,请参考以下文章

c ++分段错误将指针传递给函数

C++ 向量分段错误

如何修复 C++ 中的“分段错误”错误

删除时出现分段错误

分段错误:从二维向量中随机删除元素

C++链表删除节点