gpt4 book ai didi

c++ - 使用空指针参数和不可能的后置条件构造标准异常

转载 作者:行者123 更新时间:2023-12-01 12:21:53 26 4
gpt4 key购买 nike

考虑以下程序:

#include<stdexcept>
#include<iostream>

int main() {
try {
throw std::range_error(nullptr);
} catch(const std::range_error&) {
std::cout << "Caught!\n";
}
}

具有libstdc++的GCC和Clang调用 std::terminate并通过消息中止该程序
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid

用libc++ segfaults构造异常的Clang。

参见 godbolt

编译器的行为符合标准吗?标准 [diagnostics.range.error](C++ 17 N4659)的相关部分确实指出 std::range_error具有 const char*构造函数重载,应优先于 const std::string&重载。本节也没有说明构造函数的任何前提条件,而只说明了后置条件

Postconditions: strcmp(what(), what_­arg) == 0.



如果 what_arg是空指针,则此后置条件始终具有未定义的行为,那么这是否意味着我的程序也具有未定义的行为并且两个编译器的行为一致?如果不是,应该如何阅读标准中如此不可能的后置条件?

再次考虑,我认为它对我的程序肯定意味着未定义的行为,因为如果不这样做,那么(有效)不指向空终止字符串的指针也将被允许,这显然是没有意义的。

因此,假设这是真的,我想将问题更多地集中在该标准如何暗示这种未定义的行为上。是由于后置条件的不可能而导致调用也具有未定义的行为,还是先决条件被简单地遗忘了?

受到 this question的启发。

最佳答案

doc:

Because copying std::range_error is not permitted to throw exceptions, this message is typically stored internally as a separately-allocated reference-counted string. This is also why there is no constructor taking std::string&&: it would have to copy the content anyway.



这说明了为什么会出现段错误,该api确实将其视为真实字符串。
通常,在cpp中,如果某些东西是可选的,则将有一个重载的构造函数/函数,它不需要任何不需要的内容。因此,将 nullptr传递给未说明可选内容的函数将是未定义的行为。通常,API不会使用C字符串除外的指针。因此,恕我直言,可以安全地为期望 const char *的函数传递nullptr,这将是未定义的行为。对于这些情况,较新的API可能更喜欢 std::string_view

更新:

通常,假设一个C++ API带有一个接受NULL的指针是公平的。但是,C字符串是一种特殊情况。直到 std::string_view,没有更好的方法可以有效地传递它们。通常,对于接受 const char *的API,应该假定它必须是有效的C字符串。即指向以'\0'结尾的 char序列的指针。
range_error可以验证该指针不是 nullptr,但无法验证其是否以'\0'结尾。因此最好不要进行任何验证。

我不知道标准中的确切措词,但是该前提条件可能是自动假定的。

关于c++ - 使用空指针参数和不可能的后置条件构造标准异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60924295/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com