Guten Morgen,
ich hab eine Klasse "Thread" in der ich alle Funktionen zum starten bzw.
stoppen eines Threads benötigt werden. Diese Klasse habe ich nun
abgeleitet, so dass ich in der Klasse "CSerialPortChild" auf die
"virtuelle Methode" mit dem Namen "void ThreadFunction(void*);"
zugreifen kann.
Headerdatei "CSerialPortChild.h":
Nun möchte ich in der Methode "ThreadFunction" auf die Variablen
"receive" und "len" zugreifen. Wenn ich es so mache, wie oben gezeigt
dann erscheint folgende Fehlermeldung:
Unbehandelte Ausnahme bei 0x00411b35 in ComTerm.exe: 0xC0000005:
Zugriffsverletzung beim Schreiben an Position 0xcdcdd1cd.
Aufrufliste:
-ComTerm.exe!CSerialPortChild::ThreadFunction(void * ptr=0xcdcdcdcd)
Zeile 28 + 0x3 Bytes C++
-ComTerm.exe!Thread::my_Thread(void * para=0x0031beb0) Zeile 51 + 0x15
Bytes C++
Tiger schrieb:
> -ComTerm.exe!CSerialPortChild::ThreadFunction(void * ptr=0xcdcdcdcd)
**********
Du übergibst eine ungültige Adresse.
Der Fehler liegt also beim Aufrufer.
Da fehlt noch einiges an Quelltext.
Wo ist der Start des Threads? Was wird da übergeben?
Außerdem sollte in einer Klasse, in der mindestens eine virtuelle
Methode ist, IMMER der Destruktor auch virtuell sein.
Hat damit nichts zu tun, aber fiel mir so auf.
Klaus Wachtler schrieb:
> Da fehlt noch einiges an Quelltext.> Wo ist der Start des Threads? Was wird da übergeben?>> Außerdem sollte in einer Klasse, in der mindestens eine virtuelle> Methode ist, IMMER der Destruktor auch virtuell sein.> Hat damit nichts zu tun, aber fiel mir so auf.
Weiters:
Wenn eine Funktion in der Basisklasse virtual ist, sollte man die
gleichnamige Funktion in der abgeleiten Klasse ebenfalls explizit
virtual machen.
> Wenn ich es so mache, wie oben gezeigt> dann erscheint folgende Fehlermeldung:>> Unbehandelte Ausnahme bei 0x00411b35 in ComTerm.exe: 0xC0000005:> Zugriffsverletzung beim Schreiben an Position 0xcdcdd1cd.
...
Wenn Du das im Debugger laufen lässt, dann siehst Du auch, wie die
Funktion mit welchen Parametern aufgerufen wurde. Wie schon von Karl
Heinz beschrieben, ist der Pointer, der "ThreadFunction" übergeben
wurde, nicht initialisiert.
Der von Dir gepostete Code ist übrigens unvollständig, es fehlt
"SerialPortChild.cpp".
- auch im ZIP-Archiv.
Du brauchst doch nur am Call Stack zurückgehen und dir ansehen, wer die
ThreadFunction aufruft und welches Argument er ihr mitgibt. Die nächste
Frage ist dann, wo kommt dieses Argument her und warum wurde es nie
initialisiert.
Wenn du dich mit Threads beschäftigst, solltest du solche Dinge schon
können. Ansonsten treiben dich die schwierigeren Dinge bei Threading in
den Wahnsinn.
Tiger schrieb:
> Und wie müsste ich den Pointer von der Methode "ThreadFunction"> initialisieren?
Je nachdem was du eigentlich machen willst.
Im Moment wird die Threadfunction aufgerufen und ihr der Callbackpointer
mitgegeben m_callback. Der kriegt aber nie einen Wert (ausser NULL). Und
damit geht dann der Zugriff precv->len = 0; mächtig in die Hose.
Da dein Stack Trace einen Pointer Wert von 0xcdcdcdcd zeigt, in dem von
dir geposteten Code m_callback aber auf 0 initialisiert wird und ich bei
mir im Debugger den Pointer auch tatsächlich als 0x000000 sehe, gehe ich
davon aus, dass du den Code seit deinem ersten Post verändert hast.
Mach dich mit deinem Debugger vertraut! Der ist der Helfer in der Not.
Ohne mit ihm umgehen zu können, brauchst du nicht weitermachen.
Wo ist denn nun der Start des Threads? Dort kann man doch einen
Parameter angeben (void* oder LPVOID oder sowas), der an die
Threadfunktion durchgereicht wird. Und genau da müsstest du
die Adresse deiner Struct übergeben.
> Ich weiss nicht wo ich wie und was übergeben muss.
Müssen tust du gar nichts.
Du bist der Boss, du entscheidest, welche Daten wo in welche Funktion
übergeben werden. Aber kein Mensch schreibt dir vor, was du tun musst.
Lass mich raten.
Code von irgendwo her kopiert. Nicht duchgeschaut und auch noch keinen
Versuch gemacht das zu verstehen.
So funktioniert Programmieren nicht. Klar kann man Code von irgendwo her
kopieren. Aber man muss ihn auch verstehen. Und das mindeste ist es, im
Debugger einmal duchzusteppen.
Tiger schrieb:
> Nein dem ist nicht so. Ich hab mal vor einiger Zeit mit einem> Echtzeitbetriebssystem zu tun gehabt.
Jetzt bin ich verwirrt.
Du schreibst einen relativ banalen 100-Zeiler und blickst dann selbst
nicht mehr durch, warum eine Funktion einen ungültigen Pointer bekommt?
So, und wenn ich das richtig sehe, ist der vierte Parameter
(bei dir: this) das, was als void-Parameter an die
Threadfunktion weitergereicht wird.
Darin castet du das in einen Zeiger auf eine struct, was natürlich
schief geht.
Wenn ich jetzt nicht falsch liege, müsstest du als 4. Parameter die
Adresse der gewünschten struct angeben.
Was hattest du mit dem this an dieser Stelle vor?
Hallo Klaus Wachtler,
danke für den Rat. Allerdings weiss die Klasse Thread ja nicht, dass die
Klasse CSerialPortChild eine Struktur besitzt. Wie kann man trotz all
dem eine Adresse übergeben?
Dazu müsste man wissen, wie deine Objekte zusammenhängen und wie
alles zusammen spielen soll. Eigentlich müsstest du das wissen;
ich habe gerade keine besondere Lust, das aus einem
undokumentierten Quelltext zu rekonstruieren.
Rein technisch geht es notfalls über eine globale Variable, die
jemand vorher setzt (sicher der schlechteste Weg), oder irgendwelche
get- oder set-Methoden, über die Thread das rechtzeitig erfährt.
Gibt es sicher, aber ist auf meinem Rechner nicht drauf.
Und ehrlich gesagt muß ich auch nicht jedes obskure Datenformat
handhaben, solange es ein paar verbreitete und frei zugängliche
Formate gibt. RAR ist meines Wissens nicht frei (zumindest das
Komprimieren).
Warum nicht ZIP?
>> Was ist hier bitte schön falsch daran?
Da ist gar nichts falsch daran.
pthis->m_callback wird übergeben.
Aber pthis->m_callback wird nie auf einen Wert gesetzt!
Das würde über einen Aufruf von SetCallback gemacht, aber die Funktion
wird nie aufgerufen.
Schuss ins Blaue:
CSerialPortChild::CSerialPortChild():CSerialPort()
{
SetThreadCallBack( &this->recv );
}
Aber eigentlich müsstest DU das wissen. Du hast es ja designed.