如何在取消引用空指针时创建错误?
How to create an error on dereferencing a nullpointer?
以下代码编译无误,运行无段错误:
int* a = 0;
int& b = *a;
我们在引用中确实有一个空指针。该引用可能会在项目中移动一段时间,直到它被使用为止。使用时会产生段错误。
目前使用的编译器是MSVC 10.0和gcc 4.9。
为了便于发现错误,我希望取消引用在空指针上失败,以便在上面的代码中导致分段错误。是否有可能实现这一点以及如何实现?
您的代码的行为是未定义。
您可能 不一定 会遇到分段错误(编译器甚至可能会优化出有问题的语句),所以不要在可移植 C++ 中依赖此技术。
如果您想使程序崩溃,请使用 std::abort();
或 std::terminate();
如果要测试指针 ptr
是否为空,请使用
if (!ptr){
// ptr is nullptr
}
参考文献:
http://en.cppreference.com/w/cpp/utility/program/abort
http://en.cppreference.com/w/cpp/error/terminate
To ease the finding of the error I want the dereferencing to fail on nullpointers so that the segmentation fault is caused in the above code. Is it possible to achieve this and how?
在您提到的代码片段中没有实际取消引用发生 - 我的意思是当您定义引用时不需要内存访问。但事情更糟——即使你开始使用参考编译器,C++ 标准也没有义务检查 nullptr
,所以没有可移植的方法来自动检查它。唯一可移植的方式 - 提供手动验证它的代码:
int* a = 0;
assert( a );
int& b = *a;
这样您将在调试模式下验证正确性并且不会在发布中发布此代码。或者您可以放置始终检查它的代码。重点是——您有责任决定是否愿意支付验证指针的价格。一些编译器虽然有启用 nullptr
检测的选项,但您应该依赖编译器文档。但那种方式根本不可移植。即使您使用该标志,也无法保证在您声明引用时会发生此类验证(尤其是在启用优化时)。
补充 Bathsheba 的回答:
您可以将该代码放在 try-catch 语句中,并在指针为 nullptr 时引发异常,然后执行某些操作。例如
enum PointerException {
NullReference = 1
};
然后是这样的:
try {
if(!ptr) {
//Your pointer ain't null, do something.
} else {
//Your pointer is null, raise an exception.
throw PointerException::NullReference;
}
} catch(PointerException exception) {
//Do something with your exception
}
使用 gcc,你有地址清理器,它是一个标志,使编译器添加一些代码,当你尝试访问无效地址(越界、空指针等)时导致崩溃。
您可以在 gcc's documentation for instrumentation 中搜索 -fsanitize=address
。
使用消毒剂(通过 gcc)时,您必须 link 消毒剂。
例如:
g++ -fsanitize=address -c -o file.o file.cpp
g++ -o a.out file.o -fsanitize=address
我认为 MSVC 没有类似的机制。
以下代码编译无误,运行无段错误:
int* a = 0;
int& b = *a;
我们在引用中确实有一个空指针。该引用可能会在项目中移动一段时间,直到它被使用为止。使用时会产生段错误。
目前使用的编译器是MSVC 10.0和gcc 4.9。 为了便于发现错误,我希望取消引用在空指针上失败,以便在上面的代码中导致分段错误。是否有可能实现这一点以及如何实现?
您的代码的行为是未定义。
您可能 不一定 会遇到分段错误(编译器甚至可能会优化出有问题的语句),所以不要在可移植 C++ 中依赖此技术。
如果您想使程序崩溃,请使用 std::abort();
或 std::terminate();
如果要测试指针 ptr
是否为空,请使用
if (!ptr){
// ptr is nullptr
}
参考文献:
http://en.cppreference.com/w/cpp/utility/program/abort http://en.cppreference.com/w/cpp/error/terminate
To ease the finding of the error I want the dereferencing to fail on nullpointers so that the segmentation fault is caused in the above code. Is it possible to achieve this and how?
在您提到的代码片段中没有实际取消引用发生 - 我的意思是当您定义引用时不需要内存访问。但事情更糟——即使你开始使用参考编译器,C++ 标准也没有义务检查 nullptr
,所以没有可移植的方法来自动检查它。唯一可移植的方式 - 提供手动验证它的代码:
int* a = 0;
assert( a );
int& b = *a;
这样您将在调试模式下验证正确性并且不会在发布中发布此代码。或者您可以放置始终检查它的代码。重点是——您有责任决定是否愿意支付验证指针的价格。一些编译器虽然有启用 nullptr
检测的选项,但您应该依赖编译器文档。但那种方式根本不可移植。即使您使用该标志,也无法保证在您声明引用时会发生此类验证(尤其是在启用优化时)。
补充 Bathsheba 的回答:
您可以将该代码放在 try-catch 语句中,并在指针为 nullptr 时引发异常,然后执行某些操作。例如
enum PointerException {
NullReference = 1
};
然后是这样的:
try {
if(!ptr) {
//Your pointer ain't null, do something.
} else {
//Your pointer is null, raise an exception.
throw PointerException::NullReference;
}
} catch(PointerException exception) {
//Do something with your exception
}
使用 gcc,你有地址清理器,它是一个标志,使编译器添加一些代码,当你尝试访问无效地址(越界、空指针等)时导致崩溃。
您可以在 gcc's documentation for instrumentation 中搜索 -fsanitize=address
。
使用消毒剂(通过 gcc)时,您必须 link 消毒剂。 例如:
g++ -fsanitize=address -c -o file.o file.cpp
g++ -o a.out file.o -fsanitize=address
我认为 MSVC 没有类似的机制。