Tech or Treat! Write an article about your scariest tech disaster to win gadgets!Learn more

x
?
Solved

typeid() or dynamic_cast causes seg fault in C++ MinGW app

Posted on 2007-12-06
11
Medium Priority
?
1,844 Views
Last Modified: 2010-05-18
I am developing a simple payroll application in c++ using MinGW and wxWidgets. I created a DOS tester just to test my classes before trying to integrate them into my GUI. With my DOS application all the code compiled and executed as I expected. However, when I took my classes and included them in my project with the GUI app, everywhere I used typeid() or tried to use a dynamic_cast, I got a seg fault error and the program terminates. I tested the gui before including the code to make sure it compiled and ran successfully and it worked fine. Other pieces of code that don't use typeid() or use a dynamic_cast also run fine in the gui. I'm completely stumped and running out of time. Quick response is REALLY appreciated!
void Payroll::loadSales()
{
	int empNumber;
	double sales;
	int size = emps.size();
	ifstream inFile("c:\\sales.txt");
	inFile >> empNumber;
	for (int i = 0; i < size; i++)
	{
		if(!inFile.eof())
		{
			if(emps[i]->getEmpNumber() == empNumber)
			{	
				inFile >> sales;
				Sales* sptr;
				if((typeid(*emps[i])) == typeid(Sales))
				{
					sptr = dynamic_cast<Sales*>(emps[i]);
					sptr->setSales(sales);
				}
				inFile >> empNumber;
			}
		} else {
			continue;
		}
	}
}

Open in new window

0
Comment
Question by:rbenbolton
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
  • +2
11 Comments
 
LVL 29

Expert Comment

by:pepr
ID: 20425750
I do not know your compiler, but generally, when using dynamic_cast or typeid(), the Runtime Type Information must be enabled (via the compiler switch). The default for the swithc is usually off. Don't you observe any related warning?
0
 
LVL 29

Accepted Solution

by:
pepr earned 1500 total points
ID: 20425797
To add, the wxWidgets documentation says:

   "RTTI
    wxWidgets does not use C++ run-time type information
    since wxWidgets provides its own run-time type information
    system, implemented using macros."

Then it is likely that some default wxWidgets project do not switch the RTTI on.
0
 

Author Comment

by:rbenbolton
ID: 20425820
I did double-check to make sure that the RTTI was enabled in my project. The original problem I had was that the program would not compile precisely because rtti was not enabled. Once I enabled rtti in the project settings, my project then compiled but then I started getting the seg faults from typeid() and dynamic_cast.

Interestingly enough, I found that static_cast actually worked in my program to do what I needed; however, I still don't think that's the correct usage.

So if I were to use the wxDynamicCast in place of dynamic_cast, how would this be done? I did read some documentation on wxDynamicCast but it only seemed to apply to wxWidget objects. I could be wrong. But if anyone has an example that would be very helpful.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 29

Expert Comment

by:pepr
ID: 20426380
I have never used wxDynamicCast, but from the doc it has nothing to do with RTTI and I do not know if it is suitable also for replacing the standard dynamic_cast.

Anyway, dynamic_cast returns NULL when the cast was unsuccessful. You should check the returned value before using the pointer. What kind of pointers is stored inside your emps container?
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20426767
>> Anyway, dynamic_cast returns NULL when the cast was unsuccessful
Yes, if it's a pointer cast, if it's a reference cast it throws the exception std::bad_cast.

Why do you check typeid before the dynamic cast? It's not necessary to do that and is costing you performance. It it's a pointer dynamic_cast returns NULL on failure and if it's a reference it throws (see above).
Also, are you sure the pointers you try to dereference are in fact valid pointers? A SEGV is normally caused by trying to access invalid memory! The dynamic_cast could be a red-herring! Looking at this isolated code sample it is hard really to see what could be wrong with it. I think if I was you I'd put in some asserts to test your assumptions (for example, assert the pointers to see if your assumptions that they are valid is actually correct).
0
 
LVL 29

Expert Comment

by:pepr
ID: 20427039
evilrix: The reason for checking typeid may be that the container stores void pointers to more classes that are quite unrelated. However, I do not know if this is the case.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20427821
If you have...

    sptr = dynamic_cast<Sales*>(emps[i]);
    sptr->setSales(sales);

...you may as well have...

    sptr = reinterpret_cast<Sales*>(emps[i]);
    sptr->setSales(sales);

...because you are saying that you *know* that emps[i] is downcastable to a Sales* and you are not fielding the possibility that it isn't. Using reinterpret_cast<> is quicker and dirtier. When you use it you are saying "I know best".

If you want to handle the possibility that it isn't downcastable, then there is value in the dynamic cast, but do handle the event that it isn't downcastable (i.e. handle failed casts).

e.g.

    sptr = dynamic_cast<Sales*>(emps[i]);
    if (sptr) sptr->setSales(sales);
0
 

Author Comment

by:rbenbolton
ID: 20430567
The application I am programming is a simple payroll application and the vector emps is of Employee base class, but holds various derived classes - Salaried, Sales or Hourly object types all derived from the employee base class. I am checking the typeid() simply to verify that the object I want is in fact a Sales object. In this particular case, I could skip that step, as I know from the data I am reading in that it is in fact a Sales object, but there are other functions using similar code where I have to set data members specific to the derived class and must check typeid() to know which derived function to call.

That being said, I found that static_cast actually worked instead and didn't give me the seg faults I was seeing with dynamic_cast. However, the typeid() still throws the seg fault and I had to use a workaround to discover which object type I was dealing with by storing an empType integer in the object and doing a comparison on that.

That being said, I still have no idea why dynamic_cast and typeid() would seg fault while static_cast works.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20430592
>> I have to set data members specific to the derived class and must check typeid() to know which derived function to call.

That might be a sign of a bad design ... Usually virtual methods work better in this kind of scenario.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20433878
>> That might be a sign of a bad design ... Usually virtual methods work better in this kind of scenario.
I agree. If you can't provide abstract/virtual functions in your base class that make sense when used in a sub class context then your class hierarchy is probably wrong. If the design was right you'd have no need to dynamic cast. In fact, the use of dynamic cast can usually be considered a work-around for inadequate design.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 20438291
If dynamic_cast returns a 0, when you are expecting it to downcast, it may be that your object has been "sliced" by passing its base by value rather than by reference in a bit of sloppy polymorphism implementation.

e.g. Where derived is a class derived from a class called base...

--------8<--------
void f(base b) { // Oops forgot to make it a reference
        derived *p = dynamic_cast<derived*>(&b);
        assert(p != 0);
}

{
   derived d;
   f(d);
}
--------8<--------

The sliced object will not be dynamically downcastable, because the copy is not an instance of derived, it is an instance of base.

It is easy to make this mistake if you have a standard library container of base rather than base*.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

649 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question