【问题标题】:C++ Weird string/char* exception behaviourC++ 奇怪的字符串/char* 异常行为
【发布时间】:2017-01-11 12:29:18
【问题描述】:

这是我的异常代码:

class OptionNotFoundError: public std::exception {
public:
    OptionNotFoundError(std::string option, int position) throw()
        : option(option), position(position) {}
    OptionNotFoundError(char option_, int position) throw()
        : position(position) { option.push_back(option_); }

    virtual ~OptionNotFoundError() throw() {}

    virtual const char* what() const throw() {
        std::string what_str = "Option '" + option + "' not found in position " + std::to_string(position);
        std::cout << what_str.c_str() << std::endl;
        return what_str.c_str();;
    }

    std::string option;
    int position;
};

当抛出异常时,这是我在终端中得到的:

terminate called after throwing an instance of 'Args::OptionNotFoundError'
Option 'c' not found in position 1
  what():  

所以cout 工作正常,但是……不是返回。如果我使用return "smth",它可以正常工作。

更奇怪的是:如果我将 what_str 定义替换为

std::string what_str = "test";

我明白了

terminate called after throwing an instance of 'Args::OptionNotFoundError'
test
  what():  x�zL�

同样,cout&lt;&lt; 工作正常。但是回报……没有那么多。这是一些编码错误吗?

【问题讨论】:

  • 这个 UB 有大量重复项...
  • 考虑将std::string what_str; 设为OptionNotFoundError 类的成员变量,而不是what() 函数内部的局部变量。然后what_str 将仍然活着并踢而不是在返回时被摧毁。

标签: c++ arrays string exception stdstring


【解决方案1】:

对于第一种情况,注意what_strwhat()内部的一个局部变量,它会在离开函数作用域时被销毁,然后它返回的指针变得悬空,对它的解引用导致UB .

对于第二种情况,返回"smth" 工作正常,因为"smth"const char[5],这是string literal

字符串字面量具有静态存储持续时间,因此在程序的整个生命周期内都存在于内存中。

对于第三种情况,

如果我将what_str 定义替换为

std::string what_str = "test";

不行,因为what_str还是本地的std::string,问题和第一种情况一样。

【讨论】:

  • ……没错。起初,我内联编写了整个代码(没有“temp”字符串变量)(并且效果不佳),所以我没有想到 char* 所指的生命周期……
  • 我将 what_str 作为班级成员移到了 what() 之外,效果很好 ^^
  • @Salamandar 是的,这是一个有效的解决方案。请注意,对成员的任何更改都会使返回的指针无效,请小心。
【解决方案2】:
    return what_str.c_str();;

c_str() 返回指向std::string 内部内容的指针。

此指针仅在以下任一情况下才有效

  1. std::string 对象被销毁。

  2. std::string 对象被修改。

当您的函数返回时,从中获取此 c_str() 指针的 std::string 对象将被销毁。

这会导致未定义的行为。

您的函数返回的const char * 无效。它指向被破坏对象的内部内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    相关资源
    最近更新 更多