Problem - Falsche Verwendung von const_cast?
-
Hallo erstmal,
also ich habe folgendes Problem. Gegeben ist diese Klasse:
template <typename T> class DataSet { public: // [...] void put_data ( const void* const pvData, const unsigned int iDataBlocks ); // [...] protected: static const unsigned short& get_block_data_size ( const EBlockDataType type ) { return s_saBlockDataSize [ type ]; } // [...] const unsigned short get_block_size () const { return get_block_data_size ( get_block_data_type () ); } private: static unsigned short s_saBlockDataSize [ 9 ]; const void* m_pvData; EBlockDataType m_bdType; unsigned int m_iDataBlocks; bool m_bDataIsCopy; // [...] };Nun geht es um die Implementierung von DataSet::put_data(), diese sieht wie folgt aus:
template <typename T> void DataSet<T>::put_data ( const void* const pvData, const unsigned int iDataBlocks ) { if ( m_bDataIsCopy ) { if ( iDataBlocks != 0 ) { unsigned int iSize = iDataBlocks * get_block_size (); void* pvNewData; if ( m_pvData == NULL ) { pvNewData = new char [ iSize ]; memcpy ( pvNewData, pvData, iSize ); m_pvData = pvNewData; } else if ( iSize != m_iDataBlocks * get_block_size () ) { delete [] static_cast<const char*>( m_pvData ); pvNewData = new char [ iSize ]; memcpy ( pvNewData, pvData, iSize ); m_pvData = pvNewData; } else { memcpy ( const_cast<void*>( m_pvData ), pvData, iSize ); } m_iDataBlocks = iDataBlocks; } else { if ( m_pvData != NULL ) { /* (!) */ delete [] static_cast<const char*>( m_pvData ); /* (!) */ } m_pvData = pvData; m_iDataBlocks = iDataBlocks; } } else { m_pvData = pvData; m_iDataBlocks = iDataBlocks; } }Die Klassenvorlage DataSet wird in einer von vielen Klassen verwendet, die zu einer statischen Bibliothek kompiliert werden. Nun zum eigentlichen Problem: Wenn ich die Bibliothek nun in einem Test-Programm einbinde und dieses starte, beobachte ich folgendes Verhalten:
Wenn ich die mit (!) markierte Zeile nicht auskommentiere, bekomme ich im Testprogramm sofort nach dem Ausführen der ersten Anweisung (die vollkommen unkritisch ist und nichts mit der Bibliothek zu tun hat) einen Segmentation fault. Ist die mit (!) markierte Zeile aber auskommentiert, läuft das Programm problemlos durch.
Als kleine Ergänzung möchte ich mal beschreiben, was DataSet::put_data() überhaupt leisten soll. Ein Objekt von der Klasse DataSet soll in zwei Modi operieren können, die voneinander danach unterschieden werden, ob DataSet::m_bDataIsCopy gesetzt ist oder nicht. Ist es gesetzt, so soll DataSet::put_data() eine Kopie des von pvData adressierten Speichers an der von DataSet::m_pvData adressierten Stelle erstellen, sofern dieser groß genug ist, andernfalls soll ein anderer Speicherbereich für DataSet::m_pvData reserviert werden. Ist DataSet::m_bDataIsCopy nicht gesetzt, soll der Zeiger DataSet::m_pvData einfach auf pvData gesetzt werden.
-
Das seltsame verhalten kann ich mir auch nicht erklären, allerdings habe ich schon ähnliches erlebt wenn mann mit dem speicher in einer Bibliothek rumpfuscht.
Das Problem dabei ist, dass mit const markierte Speicherbereiche manchmal wirklich in einem rom-speicher liegen. der schreibende zugriff darauf verursacht den Fehler.
Außerdem riecht das nach schlechtem design wenn die daten per const übergeben werden und dennoch verändert werden. mach lieber eine extraklasse/funktion dafür oder ändere die signatur
-
const schrieb:
Außerdem riecht das nach schlechtem design wenn die daten per const übergeben werden und dennoch verändert werden. mach lieber eine extraklasse/funktion dafür oder ändere die signatur
Werden sie gar nicht
Wenn der Copy-Flag gesetzt ist, werden sie in einen Speicherbereich kopiert, dessen Zeiger mit const markiert ist (und eventuell überschrieben, deshalb brauche ich den const_cast). Ist der Copy-Flag nicht gesetzt, werden lediglich Referenzen angepasst. Sprich: Wenn etwas verändert wird (die Daten werden überschrieben), dann handelt es sich bei den Daten sicher um eine Kopie der per const-Referenz übergebenen Daten!EDIT: Habe soeben den ersten Beitrag nochmal editiert, habe es geschaft das Problem auf eine Zeile zu reduzieren (ein delete). Aber hier bin ich echt ratlos
