Verstehe Fehlermeldung von Visual Studio C++ 2005 nicht

Gast #1433081
Lesenswert?

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":
1
typedef struct Srecv STrecv;
2
struct Srecv 
3
{  
4
  char receive[1024];
5
  int len;
6
};
7

8
class CSerialPortChild: public CSerialPort, public Thread
9
{                             
10
public:
11
  
12
  STrecv recv;
13

14
  // contruction and destruction
15
  CSerialPortChild();
16
  ~CSerialPortChild();
17
  void ThreadFunction(void*);
18

19
protected:
20
    
21

22
};
23

24
#endif

Quelldatei "CSerialPortChild.cpp"
1
CSerialPortChild::CSerialPortChild():CSerialPort()
2
{
3

4
}
5

6

7
CSerialPortChild::~CSerialPortChild()
8
{
9

10
}
11

12

13
void CSerialPortChild::ThreadFunction(void* ptr)
14
{
15
  Srecv *precv= (Srecv*)ptr;
16

17
  while(true)
18
  {
19
    precv->len = 0;
20

21

22
  }
23

24
}

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++
#1433113
Lesenswert?

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.
Persönliche Seite #1433136
Lesenswert?

> 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.
#1433147
Lesenswert?

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.
#1433157
Lesenswert?

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.
#1433169
Lesenswert?

> 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.
#1433175
Lesenswert?

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?
Gast #1433183
Lesenswert?

1
DWORD WINAPI Thread::my_Thread(void* para)
2
{
3
    Thread* pthis=(Thread*)para;
4
  int t;
5
  if(pthis!=NULL)
6
  {
7
    pthis->ThreadFunction(pthis->m_callback);
8
    t=9;
9
    return 0;
10
  }
11
  return -1;
12
}

Was ist hier bitte schön falsch daran? Sorry, wenn ich euch damit nerve.
Ich hab nur ganz normal um Hilfe gebeten.
#1433216
Lesenswert?

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?
#1433242
Lesenswert?

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.
#1433282
Lesenswert?

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?
#1433287
Lesenswert?

Tiger schrieb:
>
1
> 
2
> DWORD WINAPI Thread::my_Thread(void* para)
3
> {
4
>     Thread* pthis=(Thread*)para;
5
>   int t;
6
>   if(pthis!=NULL)
7
>   {
8
>     pthis->ThreadFunction(pthis->m_callback);
9
>     t=9;
10
>     return 0;
11
>   }
12
>   return -1;
13
> }
14
> 
15
>
>
> 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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren