0

I am attempting to output functions common to a set of objects that share a base class and I am having some difficulty. When the objects are instantiated they are stored in an array and then I am attempting with the following code to execute functionality common to all the objects in this loop:

  if ( truck <= v ) // all types of trucks

vptr is an array of objects and the functions in the loop are common to all the objects. The code compiles fine but when I run it I get a segmentation fault when it enters this loop. I'm fairly confident that the call to the first function in this loop is what is causing the problem.

this is how I have instantiated the objects in a previous loop:

        vptr[ i ] = new Vehicle( sn, pc );

I should also mention, I'm sorry I forgot to be clear from the beginning, that in this array each object is of a different class. They all share a base class but they are derived objects of that class. Sorry for forgetting that probably important piece of information.

thanks nmr

ihtkwot
  • 1,252
  • 4
  • 16
  • 36
  • 1
    there's nothing inherently wrong from this piece of code that I can see. Show us how you setup your array. – Doug T. Nov 18 '09 at 01:47
  • This is how I declared the array: Vehicle * vptr[ maxSegment ]; and this is how I was instantiating objects: std::cin >> pc; vptr[ i ] = new Vehicle( sn, pc ); break; That bit of code is in a switch statement that takes input from the user and depending on the case will instantiate each different type of object. – ihtkwot Nov 18 '09 at 02:00
  • Vehicle * vptr[ maxSegment ]; – ihtkwot Nov 18 '09 at 02:15
  • 1
    You should probably show how the class `Vehicle` is declared, and possibly `Truck`. Is there a reason the loop is `i < numVehicles - 1`? – Sumudu Fernando Nov 18 '09 at 03:03
  • shouldn't it be allocated as Vehicle* vptr[numVehicles], i.e assert( maxSegment>= numVehicles ); – AndersK Nov 18 '09 at 04:12
  • numVehicles is a user input amount, whereas maxSegment is the maximum size the array can be, so i have a logical test to make sure that numVehicles <= maxSegment before I begin my switch statement where the objects are instantiated and set into the array – ihtkwot Nov 18 '09 at 04:25

2 Answers2

6

dynamic_cast to a pointer type returns a null pointer (aka 0, NULL) if the object isn't of the specified type. You must check the pointer before using it, or use a reference type (which throws an exception on failure instead):

if (Truck* p = dyanmic_cast<Truck*>(vptr[i])) {
  // use the pointer here
}
else {
  // vptr[i] doesn't point to a Truck
}

(Notice the nice effect of the correctly-typed pointer being scoped for you, take advantage of this when you can to improve readability.)

Community
  • 1
  • 1
1

If you use a debugger, you can easily figure out which call is causing the segmentation fault and even examine memory to see if you have a null pointer, etc.

GCC with GDB is a good example. Try this--first build your application with debugging info (to do this you add the -g switch to your compiler):

gcc -g test.c -o myProgramName

Now launch GDB:

gdb myProgramName

At the first GDB prompt, enter the 'r' command to run the program:

(gdb) r

Then, when you reach the segfault, use the 'bt' command to view the stack trace and find out where the program was when it had the bad memory access:

Program received signal SIGSEGV, Segmentation fault.
0x08048380 in testFunction2 () at test.c:17
17      *test = 1;
(gdb) bt
#0  0x08048380 in testFunction2 () at test.c:17
#1  0x0804836e in testFunction1 () at test.c:10
#2  0x0804835a in main () at test.c:5

When you compile with debugging enabled, it lets you see the source file, line number, and the actual code that caused the crash. Learning to use a debugger makes hunting down segmentation faults really easy.

Debuggers also let you examine memory--with the above example, I can check the value of the 'test' pointer:

(gdb) print test
$1 = 0x0

Whoops, the pointer was NULL when I tried to change the memory it referenced, thus I was accessing memory my program wasn't allowed to touch, causing a segmentation fault.

Try the 'print' command with objects as well--GDB is smart enough to actually break the object down and show you the value of each of the object's members. Additionally, you can use the 'printf' command to print strings, etc. while you're debugging your program.

Hope this is helpful, Maha

Jason Machacek
  • 994
  • 1
  • 8
  • 18
  • We are supposed to work logged in to our schools server and use their development tools but I have not attempted to use gdb before but hopefully they have it because we use g++. Thanks for the tip. – ihtkwot Nov 18 '09 at 02:14
  • This is what I got when using it: Program received signal SIGSEGV, Segmentation fault. 0x000000000040358d in main () – ihtkwot Nov 18 '09 at 02:27
  • Did you compile with the -g option? g++ -g myapp.cpp – Jason Machacek Nov 18 '09 at 02:32
  • 1
    Then use the 'bt' command (backtrace) I mentioned above to look at the call stack; it shows you which functions were called to get you to where you are when the program segfaults. – Jason Machacek Nov 18 '09 at 02:33