[SOLVED] [C+Windows 7] Zugriffsverletzung beim Versuch, etwas auf stdout auszugeben
-
Eine Bibliothek von mir stellt Funktionen zur Verfügung, denen man einen Pointer auf ein
struct FILE*
übergibt (zusammen mit anderen Parametern, die hier nichts zur Sache tun) und die dann intern überfprintf
Daten in den angegebenen Stream schreiben. Beispiel:void edx_print(FILE* stream,uint32_t edx) { fprintf(stream,"Flag value: %u\n",edx); return; }
Einfache Sache halt. Und im Hauptprogramm haben wir dann:
edx_print(stdout,1);
Ganz einfache Sache, und wenn ich das Ganze unter Linux laufen lasse, funktioniert das auch blendend.
Anders sieht das unter WIndows 7 (32 Bit Version mit VS2010) aus. Wenn ich hier versuche, das Programm aufzurufen, erhalte ich einen Laufzeitfehler beim Aufruf von
EnterCriticalSection
in_lock_file
in der _file.c - hervorgerufen durch denfprintf
-Call inedx_print
.Nach einer guten Packung Debugging habe ich folgendes herausgefunden:
1. Wenn ich in der Bibliotheksfunktion statt des Parameters
stream
direktstdout
verwende, schmiert das Programm nicht ab.
2. Wenn ichstdout
in einem Zeiger auf dem Stack speichere, zeigt mir der Debugger an, dassstream
undstdou
den gleichen Wert haben. Dennoch funktioniertstdout
, währendstream
nicht funktioniert.
3. Wenn ich versuche, das Problem im gleichen Modul nachzuvollziehen:#include <stdio.h> void edx_print(FILE*stream,unsigned int edx) { fprintf(stream,"Bla: %lu\n",edx); return; } int main(void) { edx_print(stdout,1); return 0; }
, dann funktioniert dies aus.
Ich dachte zuerst, dass ich durch einen vorherigen Funktionsaufruf (welcher Inline-Assembler verwendet, aber die Register werden auf dem Stack gesichert, bevor sie neu beschrieben werden) was kaputtgemacht habe, weswegen ich diese Aufrufe auskommentiert habe. Das hat aber nichts an der Zugriffsverletzung geändert - auch, wenn der Call der einzige im kompletten Programm ist.
Andere Funktionen aus der Bibliothek funktionieren übrigens ohne Probleme - egal, ob sie jetzt nur die Zeit auf
stdout
ausgeben (auch hier wieder über einenstream
-Zeiger) oder nur einfaches Bitshifting machen. Wobei die Angabe, dass es sich umstdout
handelt, jetzt immer von innerhalb der Lib kommt, und nicht von außerhalb ...Ich weiß jetzt ehrlich gesagt nicht, wo ich noch suchen soll, und habe gehofft, dass jemand hier noch einen Denkanstoß hat, wie man das eigentliche Problem weiter eingrenzen kann. Weiß jemand, ob es vielleicht unter Windows gar nicht erlaubt ist, solche File-Handles an andere Module weiterzureichen?
Vielen Dank für etwaige Hilfe im Voraus!
-
Das sieht böse aus. Ich habe es auf meinem Rechner getestet und keinen Fehler gefunden.
1.) Überprüfe mal ob die fprintf Implementierung etwas pingelig ist und fprintf(stream,"Flag value: %lu\n",edx); will.
2.) Funktioniert das Ganze wenn man statt stdout ein Dateihandle von fopen() nutzt?
3.) Überprüfe ob uint32_t stimmt, in dem du die Definition suchst.
-
@dachschaden
Welche CRT-Version verwendest du in der DLL und welche in der EXE?Wenn beide die identische DLL-Runtime verwenden (selber Compiler, beide Debug oder beide Release etc.), dann sollte es gehen.
In allen anderen Varianten kann ich mir gut vorstellen dass es Probleme gibt.
-
*stirnklatsch*
Debugmodus vs, Releasemodus ... das ABI wird da wahrscheinlich unterschiedlich sein. Und weil sich das bei Linux auch dann nicht ändert, wenn ich mit Debuginformationen kompiliere ... ja klar. Ugh, Schuss in den Fuß, jetzt funktioniert's hervorragend.
Danke für die Denkanstöße. Wieder was über Windows gelernt.
-
An der/dem ABI ändert sich nixe.
Aber du findest in MSVC Headers oft so Sachen wieclass Foo { ... #ifdef _DEBUG int m_stuffThatIOnlyNeedInDebugMode; #endif };
Und natürlich sind die Runtime DLLs eben einfach unterschiedliche DLLs. Dass die eine dann nix mit den Objekten der anderen anfangen kann, verwundert auch nicht unbedingt.
-
hustbaer schrieb:
An der/dem ABI ändert sich nixe.
Öhm, gelernt habe ich, dass, wenn sich das Layout öffentlicher Strukturen ändert, dass das dann eine Änderung der binären Schnittstelle des Programms ist (deswegen auch ABI).
Und OpenSSL sieht das auch so, als Beispie.
Und wenn sich dann das Layout von Strukturen innerhalb verschiedener Builds ändert, dann, habe ich zumindest noch gelernt, ist das eine Änderung des ABI.Die Wikipedia hat auch was dazu zu sagen
en.wikipedia.org schrieb:
ABIs cover details such as [...] the sizes, layout, and alignment of data types
Falls dem nicht so sein sollte, lasse ich mich gerne belehren und erwarte Gegeninformationen.
-
Dein Wikipediazitat passt schon.
Was du aber nicht berücksichtigst ist: es ändert sich durch das #ifdef der Source.
Es handelt sich also um zwei Verschiedene Klassen, die bloss dummerweise den selben Namen haben.Nach meiner Auffassung definiert das ABI die Regeln. Das ABI plus der Source der Standard-Library entscheiden dann wie Klassen aussehen. Ändert sich der Source ändert sich das Layout, aber deswegen ändert sich das ABI (=die Regeln) ja nicht.