从 std::exception 派生的类在 what() 上抛出无效指针错误

St.*_*rio 1 c++ exception

我试图从std::exception这样得出:

class bad_number : public std::exception
{
public:
    bad_number(const char*);
    virtual const char* what() const noexcept;
private:
    const char* num;
};

bad_number::bad_number(const char * num) : num(num){ }
const char* bad_number::what() const noexcept
{
    std::string str;
    str.append("Invalid number format:");
    str.append(num);
    char* result = new char[str.size()];
    strcpy(result, str.c_str());
    return result;
}

//The function that uses the exception
long double convert(const char *str)
{
    char *endptr;
    double result = strtold(str, &endptr);
    if (*endptr != '\0')
        throw bad_number(str);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

主要功能依次如下:

int main(int argc, char ** argv)
{
    std::vector<long double> vect;
    for(int i = 1; i < argc; i++)
    {
        try{
            vect.push_back(convert(argv[i]));
        } catch (bad_number& e){
            std::cout << e.what() << std::endl;  //free(): 
                             //invalid pointer: 0x000000000131bc40 ***
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

演示

为什么会打印无效指针错误?在我的平台(Windows 8 + cygwin)上,它会打印实际的what()返回值。这是否意味着我有UB?如果是这样,我的代码中哪里是 UB?

一般来说,我该如何解决?我想要what()打印一个人类可读的返回值。

Que*_*tin 5

std::string::size()返回字符串中的字符数,其中不包括空终止符。因此result是一个char太短,并strcpy写过去它。

此外,char每次what()调用时动态分配一个新数组确实是一个坏主意。what()声明的事实使情况变得更糟noexcept,即使new 可能抛出。

最好std::string在异常的构造函数中构造 an ,将其存储为成员变量,然后返回其c_str().