Statische Funktion - nicht-statischer Member
-
Ich benutze in meinem Programm einen Thread. Die Thread-Funktion ist statisch:
//Global deklariertes Array double m_pdResults[4]; DWORD WINAPI CV2View::ThreadFunc(LPVOID data) { CV2View *p_This = (CV2View*) data; while(true) { //Hier tritt der Fehler auf double test2 = m_pdResults[0]; .... } .... }In der selben Klasse rufe ich eine Methode auf, um das Array zu füllen:
void CV2View::OnBnClickedSettings() { // TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein. m_dlgSettings.getResults(m_pdResults); }Will ich nun aus der Threadfunktion heraus auf das Array zugreifen, bekommen ich folgende Fehlermeldungen:
error C2109: Index erfordert ein Array oder einen Zeigertyp
error C2597: Ungültiger Verweis auf nicht-statischen Member 'CV2View::m_pdResults'
Ganz offensichtlich hat die statische Funktion ein Problem mit dem Array, welches nicht statisch ist. Und nun habe ich zwei Fragen dazu:
1. Könnte mir jemand erklären, was der Grund dafür ist? Die Tatsache leuchtet mir zwar ein, aber ich würd auch gern den Grund verstehen
2. Wie könnte ich den Code am besten verändern, damit ich aus der Threadfunktion heraus auf das Array zugreifen kann?
Vielen Dank schonmal
-
Nicht-statische Elemente existieren nur mit dem jeweiligen Objekt. Und weil eine statische Funktion von sich aus keinen this-Zeiger hat, kann sie auch nicht auf die dahinterliegenden Daten zugreifen. Zum Glück hast du hier einen anderen Zeiger, über den du an ein gültiges Objekt herankommen kannst -
double test2 = data->m_pdResults[0];sollte eigentlich funktionieren.(die Alternative wäre es, dein Array ebenfalls static zu definieren, aber dann arbeiten alle CV2View's auf den selben Daten)
-
Danke für die Antwort erstmal.
double test2 = data->m_pdResults[0];
funktioniert schonmal nicht, aber ich hab einfach p_This genommen, was ja ein CV2View Pointer ist.
double test2 = p_This->m_pdResults[0];Das wird auch erstmal fehlerfrei kompiliert, allerdings erhalte ich dann sobald der Thread läuft eine Fehlermeldung
Unbehandelte Ausnahme bei 0x0041a697 in V2.exe: 0xC0000005: Zugriffsverletzung-Leseposition 0x00000000.
Das Array habe ich vorsichthalber gleich bei der Deklaration initialisiert:
double m_pdResults[4] = {1,2,3,4};Woran liegt das jetzt schon wieder?

-
Erstmal: Sorry, wegen dem falschen Zeiger.
Zweitens: Wo genau liegt denn dieses Array? Und bist du sicher, daß beide Funktionen das selbe unter m_dpResults verstehen?
Drittens: Was für einen Wert übergibst du eigentlich der Thread-Funktion (bzw. AfxBeginThread())?
-
Kein Problem mit dem Zeiger

Was meinst du mit "wo genau liegt dieses Array"? Ich kann nur sagen, dass es global ist. Oder was willst du genau wissen? Die einzigen Methoden, die auf das Array zugreifen, liegen alle in CV2View, ich hab das nochmal versucht zusammenzufassen. Das ARgument für die Thread-Funktion ist "this".Die Klasse CV2View:
double m_pdResults[4] = {1,2,3,4}; void CV2View::OnInitialUpdate() { m_pThread = CreateThread( 0, 0, ThreadFunc, this, 0, &dwThreadID ); } DWORD WINAPI CV2View::ThreadFunc(LPVOID data) { CV2View *p_This = (CV2View*) data; while(true) { double test2 = p_This->m_pdResults[0]; Sleep(50); } p_This->Invalidate(); return(0); } void CV2View::OnBnClickedSettings() { // TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein. m_dlgSettings.getResults(m_pdResults); // hier funktioniert der Zugriff double test = m_pdResults[0]; delete m_dlgSettings; }m_dlgSettings ist eine Instanz von CDialogSettings, hier nochmal die Methode:
void CDialogSettings::getResults(double* results) { results[0] = atof(m_cstrReference_1); results[1] = atof(m_cstrReference_2); results[2] = m_fReference_1; results[3] = m_fReference_2; }
-
Hm, wenn niemand außer der View-Klasse mit dem Array arbeiten will, warum schwebt es dann als globale Variable durch den Raum? (globale Variablen sind immer schlecht) Und schau dich mal in der Deklaration der Klasse um, ob du dort noch ein m_dpResults findest. (ich weiß, UN ist nicht wirklich verbindlich, aber üblicherweise steht "m_*" für eine Membervariable)
-
Allerdings, da schwebte noch ein m_pdResults in der Deklaration rum, was ich übersehen hatte. Habe es jetzt mit und ohne globales Array zum Laufen bekommen und hab mich dann für die Variante ohne globales Array entschieden. Leuchtet mir ein, dass das besser ist. Vielen Dank für deine Hilfe

-
Bitte verwende nicht CreateThread, schon gar icht wenn Du später noch die CRT oder MFC Funktionen nutzt.
Verwende AfxBginThread!
http://blog.m-ri.de/index.php/2007/11/28/createthread-und-die-crt/
-
@Martin Richter:
Was ist eigentlich der grosse Unterschied zwischen AfxBeginThread und _beginthreadex?Macht AfxBeginThread noch irgendwas für die MFC wichtiges, oder ist der Hauptunterschied der dass man ein CWinThread Objekt zurückbekommt?
-
Es ist scheinbar ähnlich wie bei der CRT, es gibt auch für die MFC einen Module Thread State. Dieser wird normalerweise beim Zerstören des assoziierten CWinThread wieder freigegeben.
Weiterhin werden einige Hooks gesetzt, dienotwendig werden, wenn GUI verwendet wird. Dito Aufräumarbeiten, falls COM verwendet wird... (AfxOleInit)
Also in einem MFC Programm sollte man auch AfxBeginThread verwenden...
Muss ehrlich sagen, dass Dein Hinweis mich auch erst dazu gebracht hat, dies näher zu analysieren.Siehe Code: AfxInitThread/AfxTermThread.
Das ist einen Blog-Eintrag wert
