将0 int literal发送到const字符串参数时访问冲突

Yan*_*niv 15 c++

在VS2015和VS2017上,此编译没有警告,并生成无法捕获的访问冲突并导致应用程序崩溃.显然,int 0被静默转换为空指针,然后假定它指向一个字符串,从而崩溃.

#include <string>
#include <iostream>
void crash(const std::string& s) {}
int main()
{
    try
    {
        crash(0);
    }
    catch (const std::exception& ex)
    {
        // never gets here!
        std::cout << "got" << ex.what() << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

如何从这样的异常中捕获并恢复?如果我从函数参数中删除const它不会编译 - 所以这可能是防止用户滥用的一种方法,但是我会失去const提供的保护,或者我会吗?编写避免此问题的原型的最佳做法是什么?

Mas*_*nes 25

对于这种特定情况,您可以通过使用C++ 11获得编译时错误std::nullptr_t,只需添加以下已删除的重载:

void crash(std::nullptr_t) = delete;
Run Code Online (Sandbox Code Playgroud)

当然,这不会保护你不会传递null(或非null终止的)char*指针...你违反了std :: string构造函数前提条件,导致未定义的行为 ; 根据定义,这是不可恢复的.

或者,如果您确实需要在运行时以可能的可恢复方式捕获这些错误,则可以编写一个const char*重载,如果给定空指针则抛出该异常,std::string const&否则调用该版本.

如果您的真实函数需要多个字符串参数,并且重载所有可能的组合似乎不可行,您可以求助于编写函数模板,对事后推断的类型执行所有检查.