segfault with dynamic_cast

M

Markus Dehmann

I get a segfault in the following scenario (I am not really used to
pointers...):

I have a base class Animal and a derived class Dog. Now I construct
two Dogs and store pointers to them in a set<Dog*>. Beforing storing,
the Dog pointers are passed through a function taking Animal pointers
and dynamic_cast'ing them to Dog pointers.

Looks good to me, but it segfaults. Why? Here is my code:


#include <iostream>
#include <stdexcept>
#include <set>
using namespace std;

class Animal {
public:
Animal(const string& theName):name(theName){}
virtual ~Animal(){}
virtual void speak(){
cout << "I do not speak." << endl;
};
const string& name;
const string& getName(){return name;}
};

class Dog : public Animal {
public:
Dog(const string& n):Animal(n){}
virtual ~Dog(){}
virtual void speak(){
cout << "Woof. I am " << getName() << endl;
};
};

class Zoo {
public:
set<Dog*> dogs;
void addAnimal(Animal* a){
Dog* d;
if((d = dynamic_cast<Dog*>(a))){
dogs.insert(d);
}else throw runtime_error("Unknown animal");
}
};

int main(){
Zoo zoo;
Dog d1("Rex");
Dog d2("Rox");
zoo.addAnimal(&d1);
zoo.addAnimal(&d2);
for(set<Dog*>::iterator it = zoo.dogs.begin(); it !=
zoo.dogs.end(); ++it){
(*it)->speak();
}
}

// (I know that zoo::dogs should be private, I just made it public
here to make code shorter)

Thanks for your comments!
Markus
 
R

Ron Natalie

Markus said:
I get a segfault in the following scenario (I am not really used to
pointers...):

I have a base class Animal and a derived class Dog. Now I construct
two Dogs and store pointers to them in a set<Dog*>. Beforing storing,
the Dog pointers are passed through a function taking Animal pointers
and dynamic_cast'ing them to Dog pointers.

Looks good to me, but it segfaults. Why? Here is my code:

First make sure your compiler doesn't have some bogus mode to disable
RTTI.

Otherwise it looks ok to me. However, your code uses one of my peevish
constructs. I hate assignments as side effects of comparisons. This
is further aggravated by the fact that you don't initialize the variable
d. It would be better style to write it
Dog* d = dynmaic_cast<Dog*>(a);
if(d) ...

-Ron

Isn't Sirius the Dog*?
 
T

Thomas Maier-Komor

Markus said:
I get a segfault in the following scenario (I am not really used to
pointers...):

I have a base class Animal and a derived class Dog. Now I construct
two Dogs and store pointers to them in a set<Dog*>. Beforing storing,
the Dog pointers are passed through a function taking Animal pointers
and dynamic_cast'ing them to Dog pointers.

Looks good to me, but it segfaults. Why? Here is my code:


#include <iostream>
#include <stdexcept>
#include <set>
using namespace std;

class Animal {
public:
Animal(const string& theName):name(theName){}
virtual ~Animal(){}
virtual void speak(){
cout << "I do not speak." << endl;
};
const string& name;
const string& getName(){return name;}
};

class Dog : public Animal {
public:
Dog(const string& n):Animal(n){}
virtual ~Dog(){}
virtual void speak(){
cout << "Woof. I am " << getName() << endl;
};
};

class Zoo {
public:
set<Dog*> dogs;
void addAnimal(Animal* a){
Dog* d;
if((d = dynamic_cast<Dog*>(a))){
dogs.insert(d);
}else throw runtime_error("Unknown animal");
}
};

int main(){
Zoo zoo;
Dog d1("Rex");
Dog d2("Rox");
zoo.addAnimal(&d1);
zoo.addAnimal(&d2);
for(set<Dog*>::iterator it = zoo.dogs.begin(); it !=
zoo.dogs.end(); ++it){
(*it)->speak();
}
}

// (I know that zoo::dogs should be private, I just made it public
here to make code shorter)

Thanks for your comments!
Markus

you pass "Rex" and "Rox" to Dog::Dog(const string &) which
create a temporary string. g++ does not seem to find out
that this temporary is needed until d1 and d2 go out of scope.
I would say this is a bug in g++, as Sun's Studio compiler does
what you would expect it to do...

Tom
 
S

Shezan Baig

Markus said:
I get a segfault in the following scenario (I am not really used to
pointers...):

I have a base class Animal and a derived class Dog. Now I construct
two Dogs and store pointers to them in a set<Dog*>. Beforing storing,
the Dog pointers are passed through a function taking Animal pointers
and dynamic_cast'ing them to Dog pointers.

Looks good to me, but it segfaults. Why? Here is my code:


#include <iostream>
#include <stdexcept>
#include <set>
using namespace std;

class Animal {
public:
Animal(const string& theName):name(theName){}
virtual ~Animal(){}
virtual void speak(){
cout << "I do not speak." << endl;
};
const string& name;




Change this to:

const string name;

(i.e., hold a copy, not a reference). After this, you should be fine.

Hope this helps,
-shez-
 
T

Thomas Maier-Komor

Thomas said:
you pass "Rex" and "Rox" to Dog::Dog(const string &) which
create a temporary string. g++ does not seem to find out
that this temporary is needed until d1 and d2 go out of scope.
I would say this is a bug in g++, as Sun's Studio compiler does
what you would expect it to do...

Tom

OK, I looked into the standard and it says that the temporary
may be destructed after the execution of the ctor. So g++ does
the right thing. Simply create a string variable and pass it
to the Dog constructor and you will be fine. As an alternative
you can change Animal::name to a normal variable (not a reference)
and everything will be OK, too. This has the advantage that
you don't have to bother around with the lifetime of the string
you pass to the constructor...

Tom
 
P

puzzlecracker

Change this to:

const string name;

(i.e., hold a copy, not a reference). After this, you should be fine.

Hope this helps,
-shez-
Can you really do that, copy the temp? let's say:

char * p="temp"; // changing anything in p is an error
char arr[5];
strpcpy(p,arr);

what is the storaga nature of above temp?
 
R

Ron Natalie

puzzlecracker said:
Can you really do that, copy the temp? let's say:
Sure, why not. The temp stays around long enough for name to get
initialized. String doesn't care what the char* it's initialized is
as long as it:
1. Is null terminated (or you pass the length)
2. It's valid while the consturctor is running.
char * p="temp"; // changing anything in p is an error
char arr[5];
strpcpy(p,arr);
Why would you want to do this?
 
K

Karl Heinz Buchegger

puzzlecracker said:
Can you really do that, copy the temp?
Sure, why not?
The temporary gets destroyed long after the copy has been made.
let's say:

char * p="temp"; // changing anything in p is an error
char arr[5];
strpcpy(p,arr);

that's completely different.
No temporary is involved.
what is the storaga nature of above temp?

There is no temporary.
If you are referring to "temp" in the above. This
is a string literal which gets created at the beginning
of your program and it lifes on until the program shuts
down. A completely different case.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,112
Latest member
VinayKumar Nevatia
Top