Что может вызвать ошибку 'signal SIGABRT' в этой действительно простой программе? - PullRequest
0 голосов
/ 17 марта 2020

Я делаю упражнения в виде функций и некоторый интерфейс для них. В настоящее время я выполнил только одно упражнение - стереть первое вхождение строки 'мы' в какой-то большей строке. Есть один парень с такой же проблемой и схожими условиями ( strcpy, вызывающий поток 1: сигнал 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

1 Ответ

2 голосов
/ 17 марта 2020

Ваша программа имеет неопределенное поведение с показанным вводом уже в строке

cin >> S;

Массив S имеет длину 10, а ввод состоит из 10 символов, но перегрузка char* >> требуется дополнительный символ для хранения нулевого терминатора строки. Это означает, что массив должен иметь как минимум размер 11. В противном случае ваша программа получает доступ к массиву вне пределов и вызывает неопределенное поведение, что означает, что программа может или не может обработать sh или сделать что-либо еще.

Вы не должны использовать char массивы для хранения строк в C ++. Вы должны использовать std::string вместо этого. В C вы не должны использовать cin >> (потому что у него его нет), и вы должны изучать / преподавать только либо C, либо C ++, но не оба смешанные. Вы не будете использовать strcpy и strstr в C ++. Стиль, который считается хорошим в двух языках, совершенно различен.

Перегрузка char* >> будет даже удалена из языка в C ++ 20. Вместо этого произойдет перегрузка, принимающая массивную ссылку char[N], которая затем прекратит чтение после символов N-1, чтобы избежать переполнения буфера, подобного этому. В нашем случае, используя S напрямую, который является массивом, ваша программа пропустит чтение последнего символа, потому что это будет go за пределами массива, в C ++ 20, но по крайней мере это прямой источник неопределенного поведения больше не будет.

Дополнительно strcpy имеет неопределенное поведение, если источник и пункт назначения перекрываются. Вместо этого используйте std::copy в C ++ или memmove в C.

...