Bug Buster 004: Can You Bust the Bug?

This is our fourth bug for you to track down and eradicate. You can find the previous bug here! How good are you at finding problems in code? The following is a code snippet compiles fine. Unfortunately, it is believed to have a problem. Does it? Take a look at the code listing and see if you can determine which of the statements that follows it is correct. One of the options is correct, while the others are not.

Can you find any issues without looking at the choices?

Bug Buster #4 

Here is the Bug Buster:

Code:

#include <iostream>
using std::cout;
using std::endl;

struct B { 
  int virtual f() { return 1; } 
};

struct D : public B { 
  int virtual f() { return 2; } 
};

void main() {
	B* pd2 = new B;
	D* pb2 = dynamic_cast<D*>(pd2);

	cout << "result is " << (pb2 ? pb2->f() : 0) << endl;

	char x;
	x = 1;
}

Your choices:

The listing will throw an exception when trying to access pb2->f().
The listing will throw a runtime exception when pb2 is declared.
The listing seems to work; however, the result is 2 will be displayed.
The listing seems to work; however, the result is 1 will be displayed.
The listing seems to work; however, the result is 0 will be displayed.
The listing seems to work; however, a memory address will be displayed.

How quickly can you find the answer? Feel free to post a comment on how quick you were! We will be posting additional snippets over the coming weeks with additional coding issues for you to bust.  You can click to the next page to find the solution.

Bug Buster 4: Solution

This example has a common C++ issue that can creep in when casting between polymorphic classes.

If you compile and run this code, it will display 0, which is not likely the solution that is wanted. This is a result of the test on pb2 that happens on the line beginning with cout. On this line, pb2 is tested for being non-null and only de-referenced if non-null. Obviously, from the result of 0 being displayed, pb2 is null.

This is a result of using dynamic_cast<>. In this listing, dynamic_cast<> is used to cast from a derived class pointer (or reference) to a pointer (or reference) to the base class and not from a base class pointer to a derived class pointer. If used to try to cast from a base pointer to a derived pointer then dynamic_cast<> returns null. When dynamic_cast<> is used, its return value should be checked for null before doing anything with it.

The problem in the example is that pd2 is a base pointer and pb2 is the derived pointer. So attempting to cast from B* (pd2) to a D* (pb2) causes pb2 to be set to null. In other words, a downcast is being tried (base to derived) whereas dynamic_cast<> is only for up-casts (derived to base).

While this could have been relatively easy to figure out in this short listing, this problem was based on a real world bug. Like many issues, this type of issue can be tricky to find. One way to reduce the number of issues that could slip through is to use a code profiling tool like Rogue Wave's Klocwork, which could possibly saving you embarrassment and time later.

# # #



Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date