2016-05-27 12 views
1

Ich habe eine C++ Anwendung, die einen Haupt-Thread und einen Poco :: Timer einen Rückruf auslösen, die in eine Datei schreibt Poco mit :: Fileoutputstream:Multi-Thread-Zugriffsverletzung Leseort C++

FileOutputStream file("test.txt", ios::binary); <-- *Access violation reading location here* 
file.write(reinterpret_cast<char *>(&data), sizeof(data)); 
file.close(); 

Der Code immer in der ersten Zeile gescheitert, hier ist der Call-Stack:!

testProject.exe std :: ctype :: verbreitern (char _Byte =‘‚) Zeile 1.716 + 0xf Bytes C++ testProject.exe std :: basic_ios> :: widen (char _Byte = '') Zeile 126 C++ testProject.exe! std :: basic_ios> :: init (std :: basic_str eambuf> * _Strbuf = 0x038ef700, bool _Istd = falsch) Zeile 135 + 0xa Bytes C++ testProject.exe! std :: basic_ostream> :: basic_ostream> (std :: basic_streambuf> * _Strbuf = 0x038ef700, bool _Istd = false) Zeile 54 C++ testProject.exe! Poco :: DateiOutputStream :: FileOutputStream (const std :: basic_string, std :: Zuordner> & Pfad = "c: \ Projekte \ TestProject \ test.txt", int Modus = 32) Zeile 93 + 0xa3 Bytes C++ testProject.exe! OPC_Server :: OnTimer (Poco :: Timer & timer = {...}) Zeile 3656 + 0x13 Bytes C++ testProject.exe! Poco :: TimerCallback :: aufrufen (Poco :: Timer & timer = {...}) Zeile 212 + 0x14 Bytes C++ testProject.exe! Poco :: Timer :: run() Zeile 197 + 0x19 Byte C++ testProject.exe! Poco :: PooledThread :: run() Zeile 200 + 0x15 Bytes C++ testProject.exe! Poco :: `anonymer Namespace ':: RunnableHolder :: run() Zeile 57 + 0x17 Bytes C++ testProject.exe! Poco :: ThreadImpl :: RunnableEntry (void * pThread = 0x00db6afc) Zeile 207 + 0x20 Bytes C++ testProject.exe! _callthreadstartex() Leitung 348 + 0xF Bytes C testProject.exe! _threadstartex (void * = PTD 0x00db6d00) Zeile 331 C

in den Stapel Tracing, schien der Zeitgeber-Thread Problem mit Lesen die Initialisierung _Byte an der Spitze der Aufrufliste in xlocale internen Header:

_Elem __CLR_OR_THIS_CALL widen(char _Byte) const 
    { // widen char 
     return (do_widen(_Byte)); <-- failed: Access violation reading location 
    } 

Zweiter Eintrag in dem Stapel in ios Standard-Header:

_Elem __CLR_OR_THIS_CALL widen(char _Byte) const 
    { // convert _Byte to character using imbued locale 
     const _Ctype& _Ctype_fac = _USE(getloc(), _Ctype); 
     return (_Ctype_fac.widen(_Byte)); <-- call the top of the stack 
    } 

dritter Eintrag in dem Stapel in ios Standard-Header:

protected: 
    void __CLR_OR_THIS_CALL init(_Mysb *_Strbuf = 0, 
     bool _Isstd = false) 
     { // initialize with stream buffer pointer 
     _Init(); // initialize ios_base 
     _Mystrbuf = _Strbuf; 
     _Tiestr = 0; 
     _Fillch = widen(' '); <-- call the second entry 

aber sehr seltsam, die gleichen Der Code läuft fehlerfrei, wenn er im Hauptthread verwendet wird.

Gibt es irgendwelche Berechtigungseinstellungen, die ich einstellen muss, damit der Poco :: Timer richtig funktioniert? Oder fehlt mir etwas sehr Offensichtliches? Danke für jede Hilfe.

EDIT: ----------------------

Poco Version: 1.7.3

Plattform: Windows

+0

Meine Vermutung ist, dass etwas in Ihrem Programm undefined Verhalten hat. Leider ist es unmöglich zu erraten, was oder wo. Teilen Sie mindestens die gesamte Callback-Funktion. (Die häufigsten Probleme sind das Vergessen der Synchronisation zwischen Threads und der Zugriff von Threads auf Objekte, deren Lebensdauer abgelaufen ist.) – molbdnilo

+0

@molbdnilo, der erste Code-Code im Callback ist derjenige, der versucht, die Datei zu schreiben. es funktioniert einwandfrei, wenn es vom Haupt-Thread aufgerufen wird, der den Timer erstellt/startet, aber nicht, wenn der Timer den Callback von einem anderen (Timer-) Thread aufruft ... – zhywu

+0

Ja, das hast du schon gesagt. Das Problem wird nicht durch diese Linien verursacht, sondern durch etwas anderes - der Absturz ist nur ein Symptom. So ist der Ruhm eines undefinierten Verhaltens. – molbdnilo

Antwort

0

Es stellt sich heraus, dass die Anwendung beendet, unmittelbar nachdem der Timer erstellt wird, aber der Ausgang ist nicht sauber gemacht, so scheint es, dass die App noch läuft und der Timer noch tickt, wenn tatsächlich wurde bereits ein Teil der Ressource freigegeben, was den Fehler verursacht.

MS '_tmain() tut etwas mehr als main() offenbar.

Leider ist es nicht _tmain(), aber _tmainCRTStartup die _tmain() ruft. Wenn _tmain() beendet wird, wird anderer Bereinigungscode ausgeführt, mein Projekt wird irgendwie nicht beendet und die Anwendung erscheint noch ", das ausgeführt wird".

+0

'_tmain' ist ein Makro. Es ist 'wmain', wenn 'UNICODE' definiert ist, sonst ist es' main'. Ich sehe nicht, was das mit Ihrem Problem zu tun hat, es sei denn, Sie greifen auf "argv" auf eine seltsame Weise zu. –

+0

@ Barmak-Shemirani, lesen Sie bitte die Antwort bearbeiten. Dies ist ein Projekt, das in Visual Studio erstellt wurde, ich bin ziemlich neu in C++, weiß nicht, wie genau ein VC++ Projekt noch funktioniert ... – zhywu

+0

Ich weiß nicht, Poco. Sie haben sehr wenig Code gezeigt. [Minimales, vollständiges und überprüfbares Beispiel] (http://stackoverflow.com/help/mcve) würde helfen. Zeigen Sie zumindest den Code für den ersten Thread und die Erstellung des zweiten Threads. Verwenden Sie auch das 'poco'-Tag. Dateizugriffsverletzung ist vorhersehbar, wenn zwei Threads versuchen, die gleiche Datei gleichzeitig mit falschem Freigabetag zu öffnen. –

Verwandte Themen