2013-03-10 86 views
1

在Visual Studio 2010中有没有一种方法可以自动捕获在NULL对象上调用成员函数的错误?也许有一些标志,在每个成员职能的乞讨中提出适当的断言?调试:自动检查是否(this == NULL)

默认行为是默默接受它,只有在访问字段时才会崩溃。但是,在某些情况下,如果晚于原始错误。


编辑:知道上一个NULL指针调用成员函数调用未定义的行为。这是我想要消除的代码中的一个错误。我希望Visual Studio有一些非标准的工具可以帮助我。

+0

您是试图解决一个真正的问题,还是一个假设的问题?如果这是一个真正的问题,我认为如下所述的某种形式的“宏观”绝对是一个合适的解决方案 - 只是将它散布在各处 - 特别是在您目前看到问题的地方。你可以随时删除它,当你已经消除了问题。如果这是一个假设的问题,那么我不确定是否有一个很好的假设答案... – 2013-03-10 14:48:50

+1

我正在解决一个真正的问题。由于代码不断发展,我预计将来会发现类似的错误。保持所有这些断言都会让我的代码变得非常混乱。 – CygnusX1 2013-03-10 17:24:48

回答

0

我不知道任何特殊的选项来检查,但你可以很容易地编写一个宏:

#define CHECK_THIS() assert(this) 

#define CHECK_THIS() do { if (this == NULL) { std::cerr << "'this' is NULL at " \ 
          << __FILE__ << ":" << __LINE__ << " in " << __func__; \ 
          exit(2); } while(0) 

(它使用了“做 - 当”,所以它可以放在任何地方,而不会干扰其他if语句等)。

然后只需在任何相关功能中添加CHECK_THIS()即可。

0

自动 - 我不知道,但你可以随时使用断言:

assert(this); 

至于this并考虑它是指“被叫”类实例关键字 - 怎么会这样空值?通过NULL指针调用?

+0

某处可以使用'ptr == NULL'命令'ptr-> doSomething()'。这就是你如何捕捉错误的方法。 – CygnusX1 2013-03-10 14:08:14

+0

@ CygnusX1以及那个案例断言是你的朋友,只需在调用其他任何东西之前调用它,然后你就完成了。它在框架代码中用得相当多。 – dtech 2013-03-10 14:10:36

+0

是的,断言可以提供帮助,但是它们也会使代码变得非常混乱。捕捉不在某处放置必要断言的错误也很容易。因此,人们为另一个交易一个错误。 – CygnusX1 2013-03-10 14:12:08

2

不,但是如果你完全接受RAII并且只使用C++ 11智能指针(从不明确地调用delete),你将很难遇到这样的错误。

+0

你仍然可以用智能指针捕捉错误,但是它们具有内置的必要断言,并且会立即发现问题。 – CygnusX1 2013-03-10 14:10:04

3

不,这是没用的。

调用指针NULL上的成员函数调用未定义的行为。顾名思义,你现在无法确定这种行为。

具体做法是:

void MyObject::foo() { 
    if (this) { throw std::logic_exception("this is NULL"); } 

    std::cout << "Hello, world!\n"; 
} 

可以通过任何符合标准的编译合理改为:

void MyObject::foo() { 
    std::cout << "Hello, world!\n"; 
} 

,因为,毕竟,标准保证this是摆在首位从来没有空!

什么可以做,但是,不靠“裸”指针:

template <typename T> 
class Pointer { 
public: 
    Pointer(): _ptr(nullptr) {} 
    Pointer(T* t): _ptr(t) {} 

    T* operator->() const { assert(_ptr); return _ptr; } 
    T& operator*() const { assert(_ptr); return *_ptr; } 

private: 
    T* _ptr; 
}; 

,然后用它像使用指针:

int main() { 
    Pointer<MyObject> value = container.find("Element"); 
    value->foo(); 
} 

如果以往任何时候都空,则在尝试拨打foo之前断言会触发。

+0

这几乎是我在我的回答评论中所建议的。直到像你这样的更有经验的人分享它,感觉它有点不太好。随着编译器和元编译器在后台执行某些样板代码生成,它可能会变得更加优雅。 – dtech 2013-03-10 14:53:19

+0

@ddriver:你说得对,编译器会自动添加一些代码工具,它变得更优雅。您可能需要检查Clang的AddressSanitizer,它会捕获无效指针访问并关闭程序,并在指针处指向空指针的行(在源代码中),并提供清晰易懂的错误消息。 – 2013-03-10 15:02:00

+0

但是,在调试模式下,运行时会做很多额外的工作,如果在使用之前检查每个指针,我怀疑这会对性能造成太大的影响。也许应该有这样一个选项...... – dtech 2013-03-10 15:08:25

1

您可以检查this是否为NULL,但如果您正在MSVS中运行,则应考虑DebugBreak选项,以强制调试中断以调查堆栈。这可能会导致错误最有效。我从Release编译中删除了检查,因为在没有调试器的情况下运行该代码会使您的应用程序自行挂起,因为没有调试器可以告诉它继续。为了避免这个问题,你可以考虑isDebuggerPresent()。

#ifdef DEBUG 
#define CHECK() if (this==NULL) DebugBreak(); 
#else 
#define CHECK() 
#endif 

的IsDebuggerPresent:

的DebugBreak MSDN上:

相关问题