Segmentation fault beim Zugriff auf polymorphes Object
Verfasst: Mo Nov 01, 2010 5:54 pm
Hi Leute, verrückter Titel, oder
Ich bastle mal wieder an Dedupe herum und bin dabei auf ein Verhalten gestoßen, das ich mir nicht erklären kann. Ich kopiere erst mal den Code hier herein:
Die Frage bezieht sich auf die freistehende Funktion CastDataVariant. Sie dient dazu, über einen Basisklassenzeiger auch auf eine Funktion zugreifen zu können, die nicht in der Basisklasse enthalten ist. Sie funktioniert wunderbar, wenn ich ein solches polymorphes Objekt dynamisch anfordere, z.B. so:
Verzichte ich auf das dynamische Erzeugen, sondern richte nur einen Basisklassenpointer auf so ein Objekt aus und versuche damit die CastDataVariant() Funktion zu füttern, bekomme ich beim Zugriff auf einen Speicherzugriffsfehler. Ist das normales Verhalten? Wenn ja, warum meckert da der Compiler nicht? Leider ist Polymorphie Neuland für mich.

Ich bastle mal wieder an Dedupe herum und bin dabei auf ein Verhalten gestoßen, das ich mir nicht erklären kann. Ich kopiere erst mal den Code hier herein:
Code: Alles auswählen
/*!
* @file datavariant.h
* @brief defines a class that can hold every datatype (Header only)
* @details
* @author Bernhard Buchwinkler
* @date august 2010
*/
#ifndef ORG_PROGGEN_DEDUPE_DATAVARIANT_H
#define ORG_PROGGEN_DEDUPE_DATAVARIANT_H
#include <typeinfo>
#include <string>
#include "statedataholding.h"
#include <iostream>
namespace Dedupe
{
/**
*Namespace Dataholding contains everything to operate the dataholding
*module
*/
namespace Dataholding
{
/**
*Namespace Variant includes two classes to handle various datatypes
*which come out of an SQLite Database (alternative to BOOST::Variant)
*/
namespace Variant
{
/**
*Data is a pure virtual baseclass to use baseclasspointers for the
*following class
*/
class Data
{
public:
virtual const std::type_info & GetType() const = 0;
};
/**
*DataVariant is a template, that can hold every datatype
*/
template<class T> class DataVariant : public Data
{
T HoldedData;
public:
/**
*To construct such a object, the datatype in the template and
*the given data must be the same datatype
*/
DataVariant( T data ) : HoldedData( data ) {};
/**
*@return the holded filetype as type_info struct
*/
virtual const std::type_info & GetType() const
{
const std::type_info &ti = typeid( HoldedData );
return ti;
}
/**
*@return the holded data
*/
T GetData() const
{
return HoldedData;
}
};
/**
*A free function to get the data from GetData while using only the
*baseclasspointer. First argument is the baseclasspointer, second
*argument is the variable where the data is written, if there were no
*cast errors.
*@return one type from CastResults
*/
template<class T> CastResults CastDataVariant( Data *incoming, T &returning )
{
/*Make sure, holded data and the
returning variable are frome the same type
*/
if( incoming->GetType() != typeid( T ) ) return DifferentDatatypes;
//Define the pointer here, cause the cast is in a different scope
DataVariant<T> *ptr = NULL;
//catch bad_cast exceptions and return an BadCastExecption error
try
{
ptr = dynamic_cast
<Dedupe::Dataholding::Variant::DataVariant<T> *>(incoming);
}
catch (std::bad_cast& bc)
{
return BadCastException;
}
if( ptr == NULL ) return CouldNotCast;
//write the data to the returning varible
returning = ptr->GetData();
return CastOK;
}
}
}
}
#endif
Code: Alles auswählen
Dedupe::Dataholding::Variant::Data *Basepointer = new Dedupe::Dataholding::Variant::Datavariant<int>(20);
Code: Alles auswählen
if( incoming->GetType() != typeid( T ) ) return DifferentDatatypes;