所以今天我遇到了一个bug,其中NULL被传递到构造函数的参数列表中,这导致应用程序中断。奇怪的是,编译器没有禁止这种情况发生。由于参数列表发生了变化,直到现在才发现问题。请参阅以下代码段:
这个对象需要3个参数,密切关注std :: string&。
class Foo {
public:
std::string myName;
unsigned int someVariable;
void * ptr;
Foo(const std::string& name, void * aPtr, unsigned int variable);
~Foo();
}
Foo::Foo(const std::string& name, void * aPtr, unsigned int variable) : myName(name), ptr(aPtr), someVariable(variable)
{
// object constructed
}
int main(int argc, char* argv[])
{
// construct an instance of Foo
Foo foo(NULL /*whoops, passed in NULL when a string should be passed in*/,
"foo",
0); // program compiles as expected, A NULL pointer runtime error occurs when executed.
}
所以基本上,如果你意外地为foo对象切换输入值,编译器就不会做任何事情。没有警报声响起,你在程序崩溃时发生了什么事。我认为应该有办法防止这种情况发生。有什么东西可以解决这个问题吗?编译器中有什么东西应该打开吗?
答案 0 :(得分:8)
实际上,通过引用传递的并不是NULL
。
std::string
有一个转换构造函数,它带有char const*
。 NULL
是一个空指针常量,因此可以在需要char const*
的地方使用它,因此从这个空指针构造一个std::string
对象。这种结构会产生不确定的行为。
向用户提供更好警告的一个选项是添加另一个具有char const*
参数的构造函数。这样,如果传入null,你可以在构造函数中轻松添加一个断言。这不是编译时检查,但如果你经常遇到这个问题,它可能总比没有好(因为它值得,我不记得了)我遇到过这个问题,所以我认为不值得努力。
答案 1 :(得分:1)
这就是我要做的事情:
Foo(const std::string& name, void * aPtr, unsigned int variable);
~Foo();
private:
Foo(int, void*, unsigned int); // Do not implement.
// This will generate a link time error when
// NULL is used as the first parameter.
注意:如果没有这个改变,我会得到编译器错误(所以这显然不是你运行的代码)。但当我解决明显的错误时,我仍然得到:
n.cpp:27: error: invalid conversion from ‘const void*’ to ‘void*’
// This is caused by the parameter -> "foo"