map eintrag zuweisen -> stürzt ab
-
Ich verwende folgendes:
#include <map> #include <string> using std::string; static enum m_ErrorStringValue { ev_MMC_COM_open, ev_MMC_COM_close }; static std::map<std::string, m_ErrorStringValue> mapErrorStringValues;mapErrorStringValues["MMC_COM_open"] = ev_MMC_COM_open; mapErrorStringValues["MMC_COM_close"] = ev_MMC_COM_close;was aber zur Zugriffsverletzung in map.h führt an der Stelle:
mapped_type& operator[](const key_type& _Keyval) { // find element matching _Keyval or insert with default mapped iterator _Where = this->lower_bound(_Keyval);Warum?
-
using std::string;
Warum machst du using std::string, wenn du nacher eh std::string schreibst?
-
drakon schrieb:
using std::string;
Warum machst du using std::string, wenn du nacher eh std::string schreibst?
Das kann ich rausnehmen, ändert aber an dem Fehler nichts.
Matthias
-
Zeig uns doch mal deinen Aufruf. Die map-Implementierung interessiert weniger.
-
Ich sehe (angesichts des zur Verfügung stehenden Quellcodes) bislang zwei Möglichkeiten:
1. Du schießt dir den Heap (lange) vor dem Zugriff kaputt, merkst es aber erst dort.
2. Du hast den Zugriff in einer Funktion, welche vom Konstruktor eines globalen Objektes aus aufgerufen wird, welches in einer anderen Übersetzungseinheit als die Map lebt.
-
Artchi schrieb:
Zeig uns doch mal deinen Aufruf. Die map-Implementierung interessiert weniger.
Was meinst du mit 'Aufruf'? Abstürzen tut das Programm an der Stelle:
mapErrorStringValues["MMC_COM_open"] = ev_MMC_COM_open;Matthias
-
Also dieses Stückchen Code funktioniert bei mir ohne einen Fehler.
-
LordJaxom schrieb:
Ich sehe (angesichts des zur Verfügung stehenden Quellcodes) bislang zwei Möglichkeiten:
1. Du schießt dir den Heap (lange) vor dem Zugriff kaputt, merkst es aber erst dort.
2. Du hast den Zugriff in einer Funktion, welche vom Konstruktor eines globalen Objektes aus aufgerufen wird, welches in einer anderen Übersetzungseinheit als die Map lebt.Ich wüsste nicht wo der Fehler sein sollte, da der Code exakt genau so in einem anderen Programm funktioniert hat, daher bin ich auch sehr planlos. _Der einzige Unterschied ist, dass ich jetzt mit Qt und nicht mit MFC programmiere und daher die Header Dateien etwas anders sind.
Das ganze wird aufgerufen durch
GlobalClasses.h
#include "PI_TranslationStage.h" extern PI_TranslationStage TranslationStage;GlobalClasses.cpp
#include "GlobalClasses.h" PI_TranslationStage TranslationStage;PI_TranslationStage.h
#include "PI_C862Mercury.h" #include "PI_TranslationStageData.h" #include <vector> #include <limits> using std::vector; #include <stdexcept> #include <map> #include <string> ... static enum m_ErrorStringValue { ev_MMC_COM_open , ev_MMC_COM_close , ...}; static std::map<std::string, m_ErrorStringValue> mapErrorStringValues; /* -------------------------------------------------------------------- */ /* class: PI_TranslationStage /* -------------------------------------------------------------------- */ class PI_TranslationStage : public PI_C862Mercury { public: PI_TranslationStage(void); PI_TranslationStage(int const iComPort, int const iSerialSpeed); ~PI_TranslationStage(void); public: void initValues(); ...TranslationStage.cpp
PI_TranslationStage::PI_TranslationStage(void) { initValues(); int result = LoadDLL(); } // ------------------------------------------------------ void PI_TranslationStage::initValues() initErrorStringValues(); ... } // ------------------------------------------------------ void PI_TranslationStage::initErrorStringValues() { mapErrorStringValues["MMC_COM_open"] = ev_MMC_COM_open; mapErrorStringValues["MMC_COM_close"] = ev_MMC_COM_close; ... }abstürzen tut das Programm dann genau an der Stelle:
_Nodeptr _Lbound(const key_type& _Keyval) const { // find leftmost node not less than _Keyval _Nodeptr _Pnode = _Root();in der Datei "xtree" beim Aufruf von
iterator _Where = this->lower_bound(_Keyval);in der Datei "map".
Wenn ich die Funktion 'initErrorStringValues' auskommentieren, dann startet das Programm komplett.
Matthias
-
Auf Dein Programm trifft Punkt zwei voll und ganz zu. Es sieht so aus als sei der Konstruktor von mapErrorStringValues noch nicht gelaufen, wenn der von TranslationStage läuft. Da beides globale Objekte sind, aber in unterschiedlichen Übersetzungseinheiten, ist die Konstruktorreihenfolge nicht definiert.
Unter anderem um dieses Problem zu umgehen benutzt man in C++ gern Singletons statt globaler Variablen. Ein einfaches Beispiel:
std::map<std::string, m_ErrorStringValue>& mapErrorStringValues() { static std::map<std::string, m_ErrorStringValue> instance; return instance; }So ist garantiert, dass beim ersten Aufruf der Funktion das Objekt konstruiert wird.
-
Ich habe es jetzt gelöst indem ich die Map definition in die Klasse gepackt habe. Aber trotzdem danke für den Hinweis zu den Singletons.
Matthias