【问题标题】:What can cause a 'signal SIGABRT' fault in this really simple program?在这个非常简单的程序中,什么会导致“信号 SIGABRT”错误?
【发布时间】:2020-06-28 14:50:03
【问题描述】:

我一直在将练习作为函数和它们的一些界面。目前我只做了一个练习,就是在一些更大的行中删除第一次出现的“我们”行。有一个人有同样的问题和类似的情况(strcpy causing Thread 1: signal SIGABRT),但我不是在使用函数 strcpy 时遇到错误,而是在我们返回 switch-case 构造之后,虽然这是必须连接的。

#include <iostream>
using namespace std;

void task1_C() {
    const int N = 10;
    char S[N];
    char rem[3] = "we";
    cout << "Input your line (should consist of 10 characters): ";
    cin >> S;
    char *p = strstr(S, rem);
    if (p) {
        strcpy(p, p + strlen(rem));
        cout << S << endl;
    }
}

void task1_Cpp() {

}

void task2_C() {

}

void task2_Cpp() {

}

void task3_C() {

}

void task3_Cpp() {

}

void task4_Cpp() {

}

void task5_Cpp() {

}

int main(){
    int input;
    cout << "Input 1-5 for C++ functions, 11-13 for C functions." << endl;
    cin >> input;
    switch(input){
        case 1: task1_Cpp(); break;
        case 2: task2_Cpp(); break;
        case 3: task3_Cpp(); break;
        case 4: task4_Cpp(); break;
        case 5: task5_Cpp(); break;
        case 11: task1_C(); break;
        case 12: task2_C(); break;
        case 13: task3_C(); break;
    }
    return 0;
}

输出:

Input 1-5 for C++ functions, 11-13 for C functions.
11
Input your line (should consist of 10 characters): sweweratwe
sweratwe
Program ended with exit code: 9

【问题讨论】:

  • 大小为10的缓冲区最多可容纳9个字符。
  • 是的,它已连接。特定代码行上的错误并不意味着它总是会在那里崩溃。 C++ 不能以这种方式工作。该程序可能会继续运行一段时间,然后最终崩溃。
  • 这也可能是内存重叠的问题(strcpy应该与不同的缓冲区一起使用AFAIK...否则你应该使用memmove)

标签: c++ xcode memory sigabrt


【解决方案1】:

您的程序具有未定义的行为,显示的输入已经在该行中

cin >> S;

数组S 的长度为10,输入由10 个字符组成,但&gt;&gt;char* 重载需要一个额外的字符来存储字符串的空终止符。这意味着数组必须至少有大小11。事实并非如此,您的程序会越界访问数组并导致未定义的行为,这意味着程序可能会或可能不会崩溃或执行任何操作。

您不应该使用char 数组在 C++ 中存储字符串。您应该改用std::string。在 C 语言中,您不应该使用 cin &gt;&gt;(因为它没有),您应该只学习/教授 C 或 C++,而不是混合使用。您不会在 C++ 中使用 strcpystrstr。两种语言认为好的风格完全不同。

&gt;&gt;char* 重载甚至将从 C++20 中的语言中删除。取而代之的是一个通过引用char[N] 数组的重载,然后它将在N-1 字符之后停止读取,以避免像这样的缓冲区溢出。在您在这里直接使用S(这是一个数组)的情况下,您的程序将跳过读取最后一个字符,因为它会超出数组的范围,在 C++20 中,但至少这个 undefined 的直接来源行为将不再存在。

此外,如果源和目标重叠,strcpy 的行为未定义。而是在 C++ 中使用 std::copy 或在 C 中使用 memmove

【讨论】:

  • 谢谢!如果我需要 C 风格,我可以用什么来代替 cin?我正在搜索它,但我不明白为什么输入一行是这样一个问题。有一个 conio 库,但它已经过时并且不适用于 mac。还有ncourses,但我遇到了一些问题。我真的不明白为什么这些事情没有简单的解决方案。过去编码真的这么复杂吗?
  • 不,在 C 语言中,您使用 scanf 和其他相关函数从标准输入获取输入。
  • @АлексейСавицкий 在纯 C 和其他低级语言中,接受任意长度的输入并非易事,是的。虽然有例如getline 这是一个 POSIX 函数。对于静态有界最大尺寸的输入,您可以使用scanf(带有正确的说明符)或fgets。参见例如this questionthis onethis one 等等。
猜你喜欢
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 2017-05-10
  • 1970-01-01
相关资源
最近更新 更多