【问题标题】:why does this code show segmentation fault?为什么这段代码显示分段错误?
【发布时间】:2017-11-25 19:14:29
【问题描述】:
#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 更改名称字段? 当我调用构造函数时,它会将值分配给变量,但在编辑时显示以下错误: 程序已停止工作。 方法也出现了同样的问题。我错过了什么。

【问题讨论】:

  • main 返回int
  • 使用 std::string.
  • 你应该阅读good C++ book
  • *a="10"; 在这里你分配一个指向文字的指针,它不是可写的内存。因此出现了段错误。
  • *a 指向字符串文字。不能修改字符串文字。然而,您的程序试图这样做,因此表现出未定义的行为。

标签: c++ segmentation-fault


【解决方案1】:

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

语句cin &gt;&gt; *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++ 编译器(以及相当多的旧编译器)默认配置为不警告此类事情,但可以配置为发出此类警告。出现编译器警告并注意它们有助于减少此类未定义行为。

【讨论】:

    【解决方案2】:

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

    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()。此外,我还为std::string 包含了&lt;string&gt; 库。最后,作为另一个建议,由于std::cin 只会读取传递给它的第一个单词而忽略其余部分,如果您想读取一个全名,那么您可以使用getline(),如下所示:

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

    【讨论】:

      【解决方案3】:

      您的代码中的问题可以最小化为这个无效代码的sn-p:

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

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

      【讨论】:

        猜你喜欢
        • 2020-08-01
        • 1970-01-01
        • 2017-08-18
        • 2010-10-19
        • 2020-02-27
        • 1970-01-01
        • 1970-01-01
        • 2021-07-24
        相关资源
        最近更新 更多