[gelöst] Problem mit Funktionszeiger
-
Okay hier mal der Code. BasisThread ist wie der Name schon sagt eine Basisklasse für einen Win32-Thread.
ReceiverThread.h
#ifndef RECEIVERTHREAD_H #define RECEIVERTHREAD_H #include <windows.h> #include "BasisThread.h" class SerialCommunicator; typedef void (SerialCommunicator::*funptr) (void); class ReceiverThread : public BasisThread { public: ReceiverThread(); ~ReceiverThread(); void setData(HANDLE* inHandle, OVERLAPPED* inReadOverlapped, funptr p, SerialCommunicator* obj); protected: virtual int run(void); private: HANDLE* h_comm; OVERLAPPED* m_readOverlapped; //void callBack(); funptr ptr; }; #endif // RECEIVERTHREAD_HReceiverThread.cpp
#include "ReceiverThread.h" #include <iostream> ReceiverThread::ReceiverThread() : BasisThread() { } ReceiverThread::~ReceiverThread() { } void ReceiverThread::setData(HANDLE* inHandle, OVERLAPPED* inReadOverlapped, funptr p, SerialCommunicator* obj) { ptr = p; std::cout << "ReceiverThread::setData(): obj = " << obj << " fun = " << p << std::endl; (*obj.*ptr)(); THREAD_SAFE_ACCESS { h_comm = inHandle; m_readOverlapped = inReadOverlapped; } END_THREAD_ACCESS } int ReceiverThread::run(void) { while(1) { // Aufgabenerfüllung } }SerialCommunication.h
#ifndef SERIALCOMMUNICATION_H #define SERIALCOMMUNICATION_H #include <windows.h> static const unsigned int RECEIVEBUFFER_LENGTH = 256; static const unsigned int COMPORT_LENGTH = 8; static const unsigned int PREFIX_LENGTH = 8; // forward declaration class ReceiverThread; class Publisher { public: virtual void dataReceived() = 0; // callback if data received on COM-Port }; class SerialCommunicator { public: static enum sc_parity { sc_parity_evenparity = 0, sc_parity_markparity, sc_parity_noparity, sc_parity_oddparity, sc_parity_spaceparity }; static enum sc_stopbits { sc_stopbits_onestopbit = 0, sc_stopbits_one5stopbit, sc_stopbits_twostopbit }; SerialCommunicator(Publisher* pubObj); ~SerialCommunicator(); HANDLE openCommunication(const char* port); BOOL setDCB( HANDLE handle, const int baudrate = 9600, const int bytesize = 8, sc_parity parity = sc_parity_noparity, sc_stopbits stopbits = sc_stopbits_onestopbit); BOOL setTimeOuts( unsigned int readIntervalTimeOut = 100, unsigned int readTotalTimeoutMultiplier = 0, unsigned int readTotalTimeoutConstant = 1, unsigned int writeTotalTimeoutMultiplier = 0, unsigned int writeTotalTimeoutConstant = 0 ); int sendData( bool& isWritten, const char* msg = NULL, bool withPrefix = false); char* receiveData( int& noOfReceivedBytes, BOOL& isRead); const char* getComPort(); BOOL closeCommunication(HANDLE handle); void incommingData(); private: HANDLE h_comm; DCB m_dcb; COMMTIMEOUTS m_timeOuts; ReceiverThread* t_receiverThread; OVERLAPPED m_readOverlapped; OVERLAPPED m_writeOverlapped; char m_comPort[COMPORT_LENGTH]; char m_progPrefix[PREFIX_LENGTH]; Publisher* p_publisherObject; char m_receiveBuffer[RECEIVEBUFFER_LENGTH]; }; #endif //SERIALCOMMUNICATION_HSerialCommunication.cpp
#include "SerialCommunication.h" #include <iostream> #include <sstream> #include "ReceiverThread.h" SerialCommunicator::SerialCommunicator(Publisher* pubObj) //: p_publisherObject(pubObj) { p_publisherObject = static_cast<Publisher*>(pubObj); memset(&m_dcb, 0, sizeof(m_dcb)); memset(&m_timeOuts, 0, sizeof(m_timeOuts)); memset(m_comPort, '\0', COMPORT_LENGTH); memset(&m_readOverlapped, 0 ,sizeof(m_readOverlapped)); memset(&m_writeOverlapped, 0 ,sizeof(m_writeOverlapped)); m_readOverlapped.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); m_writeOverlapped.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); h_comm = INVALID_HANDLE_VALUE; // Initialisierung des Handle t_receiverThread = new ReceiverThread(); m_progPrefix[0] = char(0xE6); m_progPrefix[1] = char(0xB5); m_progPrefix[2] = char(0xBA); m_progPrefix[3] = char(0xB9); m_progPrefix[4] = char(0xB2); m_progPrefix[5] = char(0xB3); m_progPrefix[6] = char(0xA9); m_progPrefix[7] = '\0'; } SerialCommunicator::~SerialCommunicator() { closeCommunication(h_comm); delete t_receiverThread; } HANDLE SerialCommunicator::openCommunication(const char* port) { closeCommunication(h_comm); strncpy_s(m_comPort, COMPORT_LENGTH -1, port, COMPORT_LENGTH -1); h_comm = CreateFile( m_comPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, // 0, ++++++++ WAS MACHT DAS FILE_FLAG_OVERLAPPED 0); if (h_comm == INVALID_HANDLE_VALUE) { //int error = GetLastError(); CloseHandle(h_comm); return NULL; } else { t_receiverThread->setData(&h_comm, &m_readOverlapped, &SerialCommunicator::incommingData, this); std::cout << "SerialCommunicator::openCommunication(): obj = " << this << " fun = " << &SerialCommunicator::incommingData << std::endl; t_receiverThread->startThread(); return h_comm; } } int SerialCommunicator::sendData(bool& isWritten, const char* msg, bool withPrefix) { std::ostringstream sstr; if(withPrefix) { sstr << m_progPrefix << msg; /*std::cout << sstr.str().c_str() << " --- " << m_progPrefix << " --- " << msg << std::endl;*/ } else { sstr << msg; } DWORD numberOfBytesWritten; if(WriteFile(h_comm, sstr.str().c_str(), sstr.str().length(), &numberOfBytesWritten, &m_writeOverlapped)) { isWritten = true; } else { if(ERROR_IO_PENDING == GetLastError()) { if( WAIT_OBJECT_0 == WaitForSingleObject( m_writeOverlapped.hEvent, 200 ) ) { isWritten = true; } else { isWritten = false; } } else { isWritten = false; } } return numberOfBytesWritten; } char* SerialCommunicator::receiveData(int& noOfReceivedBytes, BOOL& isRead) { memset(m_receiveBuffer, '\0', RECEIVEBUFFER_LENGTH); DWORD NumberOfBytesRead; if(ReadFile(h_comm, m_receiveBuffer, RECEIVEBUFFER_LENGTH-1, &NumberOfBytesRead, &m_readOverlapped)) { isRead = true; } else { if(ERROR_IO_PENDING == GetLastError()) { if( WAIT_OBJECT_0 == WaitForSingleObject( m_readOverlapped.hEvent, 200 ) ) { isRead = true; } else { isRead = false; } } else { isRead = false; } } noOfReceivedBytes = NumberOfBytesRead; return m_receiveBuffer; } BOOL SerialCommunicator::setDCB(HANDLE hCom, const int baudrate, const int bytesize, sc_parity parity, sc_stopbits stopbits) { //BOOL fSuccess = GetCommState(h_comm, &m_dcb); m_dcb.BaudRate = baudrate; m_dcb.ByteSize = bytesize; switch(parity) { case sc_parity_evenparity: m_dcb.Parity = EVENPARITY; break; case sc_parity_markparity: m_dcb.Parity = MARKPARITY; break; case sc_parity_noparity: m_dcb.Parity = NOPARITY; break; case sc_parity_oddparity: m_dcb.Parity = ODDPARITY; break; case sc_parity_spaceparity: m_dcb.Parity = SPACEPARITY; break; default: m_dcb.Parity = NOPARITY; break; } switch(stopbits) { case sc_stopbits_onestopbit: m_dcb.StopBits = ONESTOPBIT; break; case sc_stopbits_one5stopbit: m_dcb.StopBits = ONE5STOPBITS; break; case sc_stopbits_twostopbit: m_dcb.StopBits = TWOSTOPBITS; break; default: m_dcb.StopBits = ONESTOPBIT; break; } return SetCommState(h_comm, &m_dcb); } BOOL SerialCommunicator::setTimeOuts( unsigned int readIntervalTimeOut, unsigned int readTotalTimeoutMultiplier, unsigned int readTotalTimeoutConstant, unsigned int writeTotalTimeoutMultiplier, unsigned int writeTotalTimeoutConstant ) { m_timeOuts.ReadIntervalTimeout = readIntervalTimeOut; m_timeOuts.ReadTotalTimeoutMultiplier = readTotalTimeoutMultiplier; m_timeOuts.ReadTotalTimeoutConstant = readTotalTimeoutConstant; m_timeOuts.WriteTotalTimeoutMultiplier = writeTotalTimeoutMultiplier; m_timeOuts.WriteTotalTimeoutConstant = writeTotalTimeoutConstant; return SetCommTimeouts(h_comm,&m_timeOuts); } const char* SerialCommunicator::getComPort() { return m_comPort; } BOOL SerialCommunicator::closeCommunication(HANDLE handle) { t_receiverThread->killThread(); BOOL retVal = true; //if(handle != INVALID_HANDLE_VALUE) //{ retVal = CloseHandle(handle); handle = INVALID_HANDLE_VALUE; //} return retVal; } void SerialCommunicator::incommingData() { std::cout << "############################\n"; p_publisherObject->dataReceived(); }Ich habe versucht nur das Notwendigste zu posten. Kann sein dass irgendwo noch ne Klammer fehlt oder so. Das VS2005 Projekt kann ich per Mail verschicken.
Das Problem findet sich in ReceiverThread::setData(...);
Danke für die Hilfe!
-
queer_boy schrieb:
versuche den code soweit wie möglich zu kürzen, so dass der fehler aber trotzdem noch auftritt.
ach, und poste zuallererst mal die fehlermeldung, die dir dein compiler ausgibt.340 Zeilen sind nicht sehr gekürzt..
-
Der Kompiler gibt keine Fehlermeldung aus. Alles lässt sich wunderbar bauen.
Wenn ich in in der setData-Funktion von ReceiverThread bin, ist der übergebene this-Pointer (hier *obj) gleich 0.
-
Stonecold_Mario schrieb:
Der Kompiler gibt keine Fehlermeldung aus. Alles lässt sich wunderbar bauen.
Wenn ich in in der setData-Funktion von ReceiverThread bin, ist der übergebene this-Pointer (hier *obj) gleich 0.
Na dann schau mal, wieso der 0 ist. (Dann musst du aber zum Aufrufer von setData gehen.
Also hier:
SerialCommunicator::openCommunication
-
Sicher, nur sehe ich nicht warum this nun 0 ist.
t_receiverThread->setData(&h_comm, &m_readOverlapped, &SerialCommunicator::incommingData, this); std::cout << "SerialCommunicator::openCommunication(): obj = " << this << " fun = " << &SerialCommunicator::incommingData << std::endl;Die Ausgabe zeigt ja eine Objektadresse != 0
-
Wenn du da mit dem Debuger Schrit für Schritt dann in die Funktion reingehst, und vorher die Adresse nicht 0 hast und beim nächsten Schritt ist in der Funktion 0? - Kann ich mir nur schwer vorstellen.
-
Nur mal die Sachen die aufgefallen sind.
Funktionsaufruf:
this 0x009f5110 {h_comm=0x00000ee4 m_dcb={...} m_timeOuts={...} ...} SerialCommunicator * const
h_comm 0x00000ee4 void *
t_receiverThread 0x009f4d68 {h_comm=0xcdcdcdcd m_readOverlapped=0xcdcdcdcd ptr=0xcdcdcdcd } ReceiverThread *
p_publisherObject 0x009938dc {serialCom=0x009f5110 hCom=0xffffffff } Publisher *
Nächster Schritt:
obj 0x00000000 {h_comm=??? m_dcb={...} m_timeOuts={...} ...} SerialCommunicator *h_comm CXX0030: Fehler: Ausdruck kann nicht ausgewertet werden
t_receiverThread CXX0030: Fehler: Ausdruck kann nicht ausgewertet werden
p_publisherObject CXX0017: Fehler: Symbol "" nicht gefunden
Ich erkenne ein Problem. Weiß aber nicht warum es da ist.
-
Sind bezüglich der Meldungen im Debugger nur keine vernünftigen Debuginfos für die Lib erstellt worden? Wo kann ich das im VC2005 für die statische Lib einstellen (/DEBUG)? Linkereinstellungen gibt es für die Lib ja nicht?
-
Okay ich habe hier nochmal das Beispiel von heute morgen so gebaut, dass ebenfalls der selbe Fehler auftritt. Ist jetzt vielleicht einfacher nachzuvollziehen. Ich werde nicht schlau.
A.h
#ifndef A_H #define A_H class B; typedef void (B::*funptr) (void); class A { private: funptr ptr; public: void callFunction(funptr p, B* obj); }; #endif // A_HA.cpp
#include "A.h" void A::callFunction(funptr p, B* obj) { ptr = p; (*obj.*ptr)(); }B.h
#ifndef B_H #define B_H class B { public: void callHallo(); void run(); }; #endif // B_HB.cpp
#include "B.h" #include <iostream> #include "A.h" void B::callHallo() { std::cout << "Hallo Welt!\n"; } void B::run() { A* obj = new A; obj->callFunction(&B::callHallo, this); }main.cpp
#include "B.h" int main() { B* obj = new B; obj->run(); }Es scheint problematisch zu sein, wenn die Funktion callFunction der Klassen A in einer seperaten cpp-Datei implementiert wird.

Schönen Abend noch!!!
-
#include "A.h" //zuerst #include "B.h" #include <iostream> void B::callHallo() { std::cout << "Hallo Welt!\n"; } void B::run() { A* obj = new A; obj->callFunction(&B::callHallo, this); }
-
Wow danke,
genau das war das Problem. Jetzt funktioniert es auch bei meinen Prog.
Da wäre ich so schnell nicht drauf gekommen, wenn überhaupt.Was genau ist jetzt das Problem gewesen. Warum ist es wichtig die Reihenfolge der Includes zu beachten?
Nochmal danke und Gruß,
Mario
-
Stonecold_Mario schrieb:
Warum ist es wichtig die Reihenfolge der Includes zu beachten?
Ist es eigentlich nicht. Du könntest ein Problem mit einer nicht standardgemäßen Optimierung deines Compilers haben (etwa Visual C++: benutz zur Sicherheit den Schalter /vmg). Das Problem würde dann auch nicht auftreten, wenn du Zeiger auf Member nie deklarierst, bevor die betreffende Klasse definiert wurde (was meistens möglich ist; hier: vor der Klassendefinition von A den Header für B einbinden).
-
Okay danke!
Wie bist du darauf gekommen einfach die Includes zu vertauschen?
Das Programmstück welches ich dort gerade baue ist eine statische Lib. Deshalb wollte ich in jedem Fall vermeiden einen Nicht-Standard-Header zu includieren.
Bin echt froh, dass das Problem vom Tisch ist, hat echt aufgehalten.Nochmal danke auch an all die Anderen, die sich mit dem Problem beschäftigt haben.
-
Stonecold_Mario schrieb:
Das Programmstück welches ich dort gerade baue ist eine statische Lib. Deshalb wollte ich in jedem Fall vermeiden einen Nicht-Standard-Header zu includieren.
Das spielt doch keine Rolle. Es müssen ja so oder so beide Teile vorhanden sein, sonst kann das gar nicht funktionieren. Was unbedingt ferngehalten werden muss, sind Sachen, die mal gar nichts mit deinem Projekt zu tun haben. Respektive nicht zur lib gehören.
-
Ja, aber so reicht es jetzt für weitere Projekte aus, den Header der Lib und die .lib selber zu haben. Ansonsten hätte ich mindestens noch den Klasse B Header benötigt.