为什么这段代码显示分段错误?

时间:2017-06-22 13:19:05

标签: c++ segmentation-fault

#include"iostream"
using namespace std;

class xxx
{
    public:
        char **a;
        xxx();
        ~xxx();
};
xxx :: xxx()
{
    a=new char*;
    *a="10";
    cout<<endl<<*a;    // works fine
    cout<<"Enter name:";
    cin>>*a;          // segmentation fault??
}
xxx :: ~xxx()
{
   delete a;
}

main()
{
   xxx x;
    cout<<*x.a;
}

为什么我不能使用cin更改名称字段? 当我调用构造函数时,它将值赋给变量但在编辑它时显示以下错误:         程序已停止工作。 方法也出现了同样的问题。我错过了什么。

3 个答案:

答案 0 :(得分:1)

xxx的构造函数中,*a被初始化,因此它指向字符串文字的(第一个字符)。

语句cin >> *a然后尝试修改字符串文字。这给出了未定义的行为。您描述的症状是未定义行为的一种可能结果。

一个更简单的例子,没有类xxx的模糊细节将是

 #include <iostream>

 int main()
 {
     char **a = new char *;
     *a = "10";
     std::cout << std::endl << *a;    // works fine
     std::cout << "Enter name:";
     std::cin >> *a;          //  undefined behaviour here
 }

尽管与任何形式的未定义行为一样,但不能保证特定的结果/症状。

您可能会尝试调高编译器的警告级别,结果可能是语句*a = "10"中有关可疑转换的警告(例如将某些内容const转换为const) 。大多数现代C ++编译器(以及相当多的旧编译器)被配置为默认情况下不会警告这些事情,但可以配置为发出此类警告。打开编译器警告并注意它们有助于减少此类未定义的行为。

答案 1 :(得分:1)

就此而言,代码的问题非常简单。在你的构造函数中:

xxx :: xxx()
{
    a=new char*;
    *a="10";
    cout<<endl<<*a;    // works fine
    cout<<"Enter name:";
    cin>>*a;          // segmentation fault??
}

您正在尝试读入已初始化的字符串文字,然后导致Undefined Behavior。如果你想做这样的事情,并且你正在使用C ++,你应该切换到std::string,这将使你的代码更简单,而无需处理原始字符串文字和指针,如下所示:

#include <iostream>
#include <string>

class xxx
{
    public:
        std::string a;
        xxx();
        ~xxx();
};
xxx :: xxx()
{
    a = "10";
    std::cout << std::endl << a;
    std::cout << "Enter name:";
    std::cin >> a;
}

int main()
{
    xxx x;
    std::cout<< x.a;
}

在此示例中,a=new char*;delete a;等代码与析构函数本身一起被删除。我所做的其他更改包括将您的代码更改为不使用using namespace std;Read为何被视为不良做法)并将int的返回类型用于main()。此外,我还为<string>添加了std::string库。最后,作为另一个建议,由于std::cin只会读取传递给它的第一个单词并忽略其余单词,如果您想要读取全名,那么您可以使用getline()如下:

//std::cin >> a; becomes...
getline(std::cin, a);

答案 2 :(得分:0)

您的代码中的问题可以最小化到此无效代码片段:

 char *p = "foobar"; // should not compile, but would on many compilers due to backward compatibility
 p[0] = 'F';

问题是你正在尝试修改字符串文字所在的内存,即UB。