在这个非常简单的程序中,什么会导致 'signal SIGABRT' 错误?
What can cause a 'signal SIGABRT' fault in this really simple program?
我一直在做练习作为函数和一些接口。目前,我只做了一个练习,即删除较大行中第一次出现的 'we' 行。有一个人有同样的问题和相似的情况(strcpy causing Thread 1: signal SIGABRT),但我得到的错误不是在使用函数 strcpy 时,而是在我们 return 到 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
你的程序有未定义的行为,显示的输入已经在行
cin >> S;
数组S
的长度为10
,输入由10个字符组成,但是>>
的char*
重载需要一个额外的字符来存储空终止符的字符串。这意味着数组的大小必须至少为 11
。事实并非如此,您的程序越界访问数组并导致未定义的行为,这意味着该程序可能会或可能不会崩溃或执行任何操作。
您不应使用 char
数组在 C++ 中存储字符串。您应该改用 std::string
。在 C 中,你不应该使用 cin >>
(因为它没有),你应该只 learn/teach C 或 C++,而不是两者混合。您不会在 C++ 中使用 strcpy
和 strstr
。两种语言中被认为好的风格是完全不同的。
>>
的 char*
重载甚至将从 C++20 中的语言中删除。取而代之的是,将有一个通过引用获取 char[N]
数组的重载,然后它将在 N-1
个字符后停止读取以避免像这样的缓冲区溢出。在你这里直接使用 S
的情况下,它是一个数组,你的程序将跳过读取最后一个字符,因为它会超出数组的范围,在 C++20 中,但至少这个直接来源未定义的行为将不再存在。
此外,如果源和目标重叠,strcpy
会有未定义的行为。而是在 C++ 中使用 std::copy
或在 C 中使用 memmove
。
我一直在做练习作为函数和一些接口。目前,我只做了一个练习,即删除较大行中第一次出现的 'we' 行。有一个人有同样的问题和相似的情况(strcpy causing Thread 1: signal SIGABRT),但我得到的错误不是在使用函数 strcpy 时,而是在我们 return 到 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
你的程序有未定义的行为,显示的输入已经在行
cin >> S;
数组S
的长度为10
,输入由10个字符组成,但是>>
的char*
重载需要一个额外的字符来存储空终止符的字符串。这意味着数组的大小必须至少为 11
。事实并非如此,您的程序越界访问数组并导致未定义的行为,这意味着该程序可能会或可能不会崩溃或执行任何操作。
您不应使用 char
数组在 C++ 中存储字符串。您应该改用 std::string
。在 C 中,你不应该使用 cin >>
(因为它没有),你应该只 learn/teach C 或 C++,而不是两者混合。您不会在 C++ 中使用 strcpy
和 strstr
。两种语言中被认为好的风格是完全不同的。
>>
的 char*
重载甚至将从 C++20 中的语言中删除。取而代之的是,将有一个通过引用获取 char[N]
数组的重载,然后它将在 N-1
个字符后停止读取以避免像这样的缓冲区溢出。在你这里直接使用 S
的情况下,它是一个数组,你的程序将跳过读取最后一个字符,因为它会超出数组的范围,在 C++20 中,但至少这个直接来源未定义的行为将不再存在。
此外,如果源和目标重叠,strcpy
会有未定义的行为。而是在 C++ 中使用 std::copy
或在 C 中使用 memmove
。