繁体   English   中英

为什么cout << * s << endl会产生段错误?

[英]Why does cout << *s << endl produce a segfault?

我在C ++类的实践考试中有这个问题,我们应该写输出是什么,或者它是否产生错误。 运行此代码会产生分段错误,但有人可以解释原因吗? 对我来说很好。

    string *s;
    s = (string *) "This is my house. I have to defend it.";
    cout << *s << endl;

当未指向std::string类型的对象时,通过类型为std::string*的指针进行间接具有未定义的行为。

字符串文字不是std::string类型的对象。 字符串文字是字符数组。 std::string是在标题<string>定义的类。

运行此代码会产生分段错误,但有人可以解释原因吗?

您通过不指向兼容类型对象的指针进行间接访问。 您的程序的行为是不确定的。


PS永远不需要使用C样式转换(例如(type)expression )。 它可以轻松地抑制有用的编译错误并将其替换为未定义的行为。 应该避免。

如果您在这里没有使用C风格的转换,那么类型系统会在开始运行该程序之前警告您该错误。 在这种情况下,您可能会看到类似于以下内容的错误消息:

error: cannot convert 'const char [39]' to 'std::string*' {aka 'std::basic_string<char>*'} in assignment

帮助您意识到类型不匹配。

您需要了解字符串文字和类std::string之间的区别。

将字符串文字转换为std::string*是未定义的行为。 当代码执行*s由于s无效,这在这里表现为分段错误。

如果没有C样式转换(string *)s = (string *) "T..."; 编译器将发出错误。

始终对C ++中的C样式转换提出疑问。

可能的问题(或至少一个问题)是s没有分配内存的事实。 您需要使用new关键字,然后尝试执行以下操作:

string *s;
s = new string("This is my house. I have to defend it.");
cout << *s << endl;

当然,理论上您也需要使用delete。

std :: string倾向于归结为以下形式:

struct string
{
  char* _begin;
  char* _end;
  char* _capacity;
};

您定义的文本字符串如下所示:

const char* const text = "This is my house. I have to defend it."

因此,您正在从类型(char *)转换为类型(string *)。 现在,这意味着_begin将存储位置“ This is” ,而_end将存储位置“ my house”

当将字符串打印到std :: cout时,它将取消引用s的指针,并尝试查找字符串大小,通常这样实现:

size_t string::size() const { return _end - _begin; }

鉴于_begin和_end不存储指针值(它们只是文本的随机位),这将导致cout尝试打印非常错误数量的字符_(因为_begin和end中的存储位置是无意义的)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM