CygnusX1
CygnusX1

Reputation: 21808

Debugging: Automatically check if (this==NULL)

Is there a way in Visual Studio 2010 to automatically catch a bug of calling a member function on a NULL object? Some flag perhaps, that puts an appropriate assertion at the begging of every member function?

The default behavior is to silently accept it and only crash when a field is accessed. In some cases however if is much later then the original error.


Edit: I know that calling member function on a NULL pointer invokes undefined behavior. It is a bug in my code that I want to eradicate. I hope that Visual Studio has some non-standard tool that could assist me.

Upvotes: 1

Views: 1371

Answers (5)

EGOrecords
EGOrecords

Reputation: 1969

You can check if this is NULL, but if you are running in MSVS, you should consider the DebugBreak - option, to force a debug break to investigate the Stack. This could lead to the bug most effective. I removed the checking from Release compiles, because running that code without a debugger will make your application hang itself, because no debugger can tell it to continue. To avoid that issue, you can think about isDebuggerPresent().

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

IsDebuggerPresent:

DebugBreak on MSDN:

Upvotes: 1

Matthieu M.
Matthieu M.

Reputation: 300059

No, and it would be useless.

Calling a member function on a NULL pointer invokes undefined behavior. As the name imply, you cannot be sure of the behavior at this point.

Specifically:

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

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

Can reasonably changed by any conforming compiler to:

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

since, after all, the Standard guarantees that this is NEVER null in the first place!

What can be done, however, is not relying on "bare" pointers:

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;
};

And then using it like you would a pointer:

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

And if ever it is null, then the assert fires before the call to foo is attempted.

Upvotes: 2

David
David

Reputation: 28188

No, but if you fully embrace RAII and only use C++11 smart pointers (never explicitly calling delete) you'll be hard pressed to ever run into such a bug.

Upvotes: 2

dtech
dtech

Reputation: 49319

Automatic - I don't know, but you can always use an assert:

assert(this);

As for this and considering it is a keyword that refers to the "callee" class instance - how can it be NULL? Call through a NULL pointer?

Upvotes: 0

Mats Petersson
Mats Petersson

Reputation: 129464

I'm not aware of any special option to check for this, but you could easily write a macro:

 #define CHECK_THIS()  assert(this)

or

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

(It's using "do - while" so that it can be placed anywhere without interfering with other if-statements, etc).

Then just add CHECK_THIS() in any relevant functions.

Upvotes: 0

Related Questions