none
Critical error detected c0000374 bei Aufruf native code von managed dll RRS feed

  • Frage

  • es geht um folgendes:
    - um eine native-C-dll soll ein .com-wrapper in c# geschrieben werden.

    hier ein paar auszüge:
    die c-dll (erzeugt libhpdf.dll):

    __declspec(dllexport) (const char *) HPDF_GetVersion (void)
    {
    	return "2.2.1";
    }
    

    der dazu passende .net-c#-wrapper, der nach außen hin eine com-schnittstelle darstellen soll (erzeugt PDFLib.dll im gleichen Verzeichnis, wie libhpdf.dll)
    Projekteinstellungen:
     - "Application" -> "assembly Information" "make Assembly Com-visible" (angehakt)
     - "Build" -> "Reisgiter for COM-Interop" (angehakt)
     
    => Beim Build fällt die dll und die tlb ins Ausgabeverzeichnis


    [Guid("A3AFE8C9-FB0D-4262-96CD-C88224E4A7D5"), 
    InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IComInterface
    {
    	void DoPDFTestStuff();
    }
    
    [ClassInterface(ClassInterfaceType.None),
    Guid("D5835BB2-8A08-4FDC-9F14-77AFDD6C1A5D")]
    public class PDFMethods : IComInterface, IDisposable
    {
    	public PDFMethods()
    	{
    		System.Diagnostics.Debug.WriteLine("PDFMethods - ctor");
    	}
    
    	public void Dispose()
    	{
    		System.Diagnostics.Debug.WriteLine("Dispose");
    	}
    
    	public void DoPDFTestStuff()
    	{
    		System.Diagnostics.Debug.WriteLine("PDFMethods - DoPDFTestStuff");
    		System.Diagnostics.Debug.WriteLine("libhpdf-" + HPdfDoc.HPdfGetVersion());
    	}
    }
    
    internal class HPdfDoc{
    	[DllImport("libhpdf.dll")]
    	private extern static string HPDF_GetVersion();
    
    	public static string HPdfGetVersion()
    	{
    		System.Diagnostics.Debug.WriteLine("los");
    		return HPDF_GetVersion();
    	}
    }
    

    nun geht es um den client, der den .net-Wrapper benutzt.
    die erste variante ist eine c#-windows-app.
    diese importiert per referenz die .net-assembly und ruft die methoden auf (NICHT per com)
    soweit läuft das auch alles super

    probleme gibt es allerdings, wenn ein c++-native-client per com auf die methoden zugreifen möchte:

    //stdAfx.h
    #import "..\\..\\..\\..\\__bin\\i386\\Debug\\PDFLibrary\\PDFLibrary.tlb" named_guids
    
    BOOL CPDFLibraryTestComDlg::OnInitDialog(){
    	//NULL-Prüfungen, Exceptionhandling, Asserts usw. entfernt
    	CoInitialize(NULL);
    
    	PDFLibrary::IComInterfacePtr _pPDFLib;
    	_pPDFLib = PDFLibrary::IComInterfacePtr(__uuidof(PDFLibrary::PDFMethods)); //(1)
    	_pPDFLib->DoPDFTestStuff(); //(2)
    }
    

    und hier passiert nun folgendes:
    - (1) wird fehlerfrei ausgeführt
    - (2) führt noch in den .net-Wrapper. die ausgabe "PDFMethods - DoPDFTestStuff" kommt noch, man kann dort per breakpoint anhalten. will man jedoch dann die methode aus der native-c-dll ausführen, landet man mit einer messagebox im debugger. dort und im ausgabefesnter steht dann:

    Critical error detected c0000374
    Windows has triggered a breakpoint in PDFLibraryTestCom.exe.

    This may be due to a corruption of the heap, which indicates a bug in PDFLibraryTestCom.exe or any of the DLLs it has loaded.

    This may also be due to the user pressing F12 while PDFLibraryTestCom.exe has focus.

    The output window may have more diagnostic information.

    jemand einen hinweis, was da falsch läuft?

    Donnerstag, 29. März 2012 13:39

Antworten

Alle Antworten

  • Es kann sein dass Dein Problem eine Analyse durch dem Microsoft Application Verifier Tool benötigt.

    How to debug heap corruption errors?

    Wired runtime error (c0000374)

    ich habe versucht, mir das ganze anzusehen - leider mit wenig zählbarem erfolg. entweder bediene ich die tools falsch oder ich bin nicht in der lage, ihre ausgaben zu interpretieren. ich hab unten mal ein logfile vom application verifier gepostet. was soll mir das nun sagen? von den dort erwähnten methoden liegt keine in meinen sourcen

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <avrf:logfile xmlns:avrf="Application Verifier">
    	<avrf:logSession TimeStarted="2012-03-30 : 14:44:19" PID="16112" Version="2">
    		<avrf:logEntry Time="2012-03-30 : 14:44:25" LayerName="Heaps" StopCode="0x10" Severity="Error">
    			<avrf:message>Corrupted start stamp for heap block.</avrf:message>
    			<avrf:parameter1>1c1000 - Heap handle used in the call.</avrf:parameter1>
    			<avrf:parameter2>1e240 - Heap block involved in the operation.</avrf:parameter2>
    			<avrf:parameter3>0 - Size of the heap block.</avrf:parameter3>
    			<avrf:parameter4>0 - Corrupted stamp value.</avrf:parameter4>
    			<avrf:stackTrace>
    				<avrf:trace>vrfcore!VerifierRegisterLayerEx+11b ( @ 0)</avrf:trace>
    				<avrf:trace>verifier!VerifierStopMessage+5660 ( @ 0)</avrf:trace>
    				<avrf:trace>verifier!VerifierStopMessage+59fe ( @ 0)</avrf:trace>
    				<avrf:trace>verifier!VerifierStopMessage+5ec0 ( @ 0)</avrf:trace>
    				<avrf:trace>verifier!VerifierStopMessage+3ccb ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!RtlpNtMakeTemporaryKey+4eeb ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!EtwSendNotification+d40d ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!RtlEnumerateGenericTableWithoutSplaying+783 ( @ 0)</avrf:trace>
    				<avrf:trace>vfbasics!+691cfe9c ( @ 0)</avrf:trace>
    				<avrf:trace>kernel32!HeapFree+14 ( @ 0)</avrf:trace>
    				<avrf:trace>vfbasics!+691d1024 ( @ 0)</avrf:trace>
    				<avrf:trace>ole32!CoInitializeEx+1c2 ( @ 0)</avrf:trace>
    				<avrf:trace>ole32!CoTaskMemFree+13 ( @ 0)</avrf:trace>
    				<avrf:trace>mscorwks!LogHelp_TerminateOnAssert+2e5c ( @ 0)</avrf:trace>
    				<avrf:trace>mscorwks!LogHelp_TerminateOnAssert+646e ( @ 0)</avrf:trace>
    				<avrf:trace>mscorwks!CreateApplicationContext+21ba ( @ 0)</avrf:trace>
    				<avrf:trace>mscorwks!+79c51cc6 ( @ 0)</avrf:trace>
    			</avrf:stackTrace>
    		</avrf:logEntry>
    		<avrf:logEntry Time="2012-03-30 : 14:44:28" LayerName="Memory" StopCode="0x60D" Severity="Error">
    			<avrf:message>Unexpected exception raised in DLL entry point routine.</avrf:message>
    			<avrf:parameter1>2666fe0 - DLL name (use du to dump it).</avrf:parameter1>
    			<avrf:parameter2>1bed18 - Exception record. Use .exr to display it.</avrf:parameter2>
    			<avrf:parameter3>1bed34 - Context record. Use .cxr to display it.</avrf:parameter3>
    			<avrf:parameter4>28befd8 - Verifier dll descriptor</avrf:parameter4>
    			<avrf:stackTrace>
    				<avrf:trace>vfbasics!+691cf017 ( @ 0)</avrf:trace>
    				<avrf:trace>vfbasics!+691cf5e0 ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!RtlQueryInformationActivationContext+1b7 ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!RtlExitUserProcess+e6 ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!RtlExitUserProcess+68 ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!EtwSendNotification+9c1f ( @ 0)</avrf:trace>
    				<avrf:trace>ntdll!RtlInitializeExceptionChain+36 ( @ 0)</avrf:trace>
    			</avrf:stackTrace>
    		</avrf:logEntry>
    	</avrf:logSession>
    </avrf:logfile>

    und mit windbg bin ich auch mal an die .exe gegangen, der gibt mir als erste fehlermeldung das hier aus:

    ModLoad: 0fa60000 0fb90000   D:\WinSPC\WinSPC20\__BIN\i386\Debug\PDFLibrary\libhpdf.dll
    HEAP[PDFLibraryTestCom.exe]: Invalid address specified to RtlSizeHeap( 002B0000, 0001E220 )
    (2c34.37a4): Break instruction exception - code 80000003 (first chance)
    eax=0001e218 ebx=0001e218 ecx=77997433 edx=0016dd89 esi=002b0000 edi=0001e220
    eip=779a878e esp=0016dfcc ebp=0016dfd0 iopl=0         nv up ei pl nz na po nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
    ntdll!DbgBreakPoint:
    779a878e cc              int     3

    meine ganz persönliche, wenig untermauerte und eher diffuse theorie sieht besagt, daß es evt. mit irgendwelchen build-einstellungen zu tun hat? unicode oder nicht, mfc/atl oder nicht, bstr vs. lpctstr vs. char*, linkereinstellungen, bindungs usw. kann man sich sowas vorstellen?

    daß der unmanged code der c-dll grundsätzlich fehlerhaft ist, glaube ich eher nicht. die habe ich zwar im quellcode, der ist aber nicht von mir sondern von http://libharu.org/wiki/Main_Page

    wenn ich die binarys downloade statt die dll selbst zu bauen, ändert das allerdings am fehlerverhalten auch nichts, also tippe ich eher auf die c#-c schnittstelle


    • Bearbeitet suriel6666 Freitag, 30. März 2012 12:58
    Freitag, 30. März 2012 12:50
  • Hallo suriel6666,

    Schau Dir mal die Antwort von Brian Muth aus dem folgenden Diskussionsfaden an. Vielleicht kann sie Dir weiterhelfen.

    Baffling COM leak (isolated)

    „Heap corruption is most likely related to bugs in the native code aspect of your code, so that's the first place to look. My personal view is that a proper code review is the proper way to catch buffer overruns, double delete's, etc., preferably with eyes other than the original author.”

    Noch zum lesen: http://www.daviddahlbacka.com/BugCleaner/BugCleaner.book.pdf

    Grüße,

    Robert


    Robert Breitenhofer, MICROSOFT  Twitter Facebook
    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip„Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Freitag, 30. März 2012 16:07
    Moderator
  • Callstack?

    Typelib evtl. falsch- Alle Module noch mal übersetzen.
    Ist sicher gestellt, dass die DLL auch wirklich geladen werden kann. Bzw. kannst Du sehen, dass Diene native DLL geladen wird (debugger)?


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de

    Samstag, 31. März 2012 06:18
    Moderator
  • Callstack?

    Typelib evtl. falsch- Alle Module noch mal übersetzen.
     Ist sicher gestellt, dass die DLL auch wirklich geladen werden kann. Bzw. kannst Du sehen, dass Diene native DLL geladen wird (debugger)?

    callstack kann ich gern am montag nochmal posten, der der sieht so aus, wie ich es erwarte. der oberste eintrag ist der der extern static string HPDF_GetVersion() aus der c#-dll. in der native dll lande ich nicht mehr

    alles rebuilden hab ich mehrfach versucht. procmon zeigt auch an, daß die richtigen dateien angezogern werden.

    ja, ich kann auch im debugger sehen, daß die native dll auch tatsächlich geladen wird. nehme ich die weg (umbenennen) gibt es auch eine andere fehlermeldung (einstiegspunkt nicht gefunden, dll nicht gefunden oder sowas)

    was mich verwirrt ist eben auch, daß alles funktioniert, wenn ich als client eine c#-app nehme nicht keine c++-app per com. der der prinzipielle zugriff des c#-wrappers auf den native-teil klappt dann doch

    Samstag, 31. März 2012 11:23
  • Es kracht in Deiner nativen Funktion? Das kann doch gar nicht sein...

    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de

    Sonntag, 1. April 2012 16:09
    Moderator
  • Es kracht in Deiner nativen Funktion? Das kann doch gar nicht sein.

    nein, nicht IN der native funktion sondern bei deren aufruf vom c#-teil aus.

    nur, damit wir hier vom gleichen reden, es gibt:

    1. native c-lib

    2. c#-wrapper der als com-server registriert wird

    3.a c#-client, der 2. benutzt (aufrufe dann nicht per com)

    3b. c++-client, der 2. per com benutzt

    bei 3. a funktioniert alles tadellos,

    bei 3. b knallts beim aufruf von 2. nach 1. der aufruf con 3.b in 2 klappt noch

    Sonntag, 1. April 2012 20:39
  • Callstack?

    hier gibts einen Callstack:

    www.d-o-r-n.de/transfer/Stacktrace.gif

    die blau hinterlegte zeile ist dabei generierter quelltext:

    inline HRESULT IComInterface::DoPDFTestStuff ( ) {
        HRESULT _hr = raw_DoPDFTestStuff();
        if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
        return _hr;
    }

    man landet schon noch in der c#-dll (trace ausgabe von dort kommt), dann gehts aber schief, wenn der native-teil aufgerufen werden soll (in der native dll landet man nicht mehr)

    Montag, 2. April 2012 09:21
  • > http://www.d-o-r-n.de/transfer/Stacktrace.gif

    Lad mal sos und zeig mal den managed callstack an...

    Für mich sieht dies nach einem marshalling Problem aus...


    Jochen Kalmbach (MVP VC++)
    • Als Antwort markiert suriel6666 Montag, 2. April 2012 11:08
    Montag, 2. April 2012 09:29
  • Für mich sieht dies nach einem marshalling Problem aus...

    ja, sah es für mich auch aus und nach weiteren herumfehlversuchen usw. ist es mir tatsächlich geglückt, das ganze in gang zu bekommen. wen es interessiert: die native funktion

    const char * HPDF_GetVersion ()

    kann (natürlich *g) nicht einfach so auf einen c#-string gemarshaled werden:

    	[DllImport("libhpdf.dll")]
    	private extern static string HPDF_GetVersion();
    
    	public static string HPdfGetVersion()
    	{
    		System.Diagnostics.Debug.WriteLine("los");
    		return HPDF_GetVersion();
    	}


    sondern SO IST ES RICHTIG:

    [DllImport("libhpdf.dll")] private extern static IntPtr HPDF_GetVersion(); public static string HPdfGetVersion() {

    return Marshal.PtrToStringAnsi(HPDF_GetVersion()); }

    danke allen, die sich daran versucht haben

    Montag, 2. April 2012 11:08
  • Wie ist denn diese Methode "HPDF_GetVersion" definiert?
    Für mich sieht das so aus, als ob Du hier ein Speicherleck erzeugst...


    Jochen Kalmbach (MVP VC++)
    Montag, 2. April 2012 11:23
  • Wie ist denn diese Methode "HPDF_GetVersion" definiert?
    Für mich sieht das so aus, als ob Du hier ein Speicherleck erzeugst...


    ach herrje, tatsächlich? also die ist downgeloadet von http://libharu.org/ und sieht so aus:

    #ifdef HPDF_DLL_MAKE
    #    define HPDF_EXPORT(A)  __declspec(dllexport) A  __stdcall
    #else
    #    ifdef HPDF_DLL_MAKE_CDECL
    #        define HPDF_EXPORT(A)  __declspec(dllexport) A
    #    else
    #        ifdef HPDF_SHARED_MAKE
    #            define HPDF_EXPORT(A)  extern A
    #        endif /* HPDF_SHARED_MAKE */
    #    endif /* HPDF_DLL_MAKE_CDECL */
    #endif /* HPDF_DLL_MAKE */
    
    
    #define HPDF_VERSION_TEXT "2.2.1"
     
    HPDF_EXPORT(const char *) HPDF_GetVersion (void)
    {
    return HPDF_VERSION_TEXT;
    }
    
    


    ich hab das ganze (hoffentlich richtig) mit HPDF_DLL_MAKE_CDECL übersetzt, es sollte also

    __declspec(dllexport) const char* HPDF_GetVersion()

    {

    return "2.2.1";

    }

    entstehen. alles ok damit?

    Montag, 2. April 2012 11:52
  • Wenn es ein statischer String ist, dann passt es.
    Ich hatte nur befürchtet, dass der Speicher in der Funktion dynamisch allokiert wird...


    Jochen Kalmbach (MVP VC++)
    Montag, 2. April 2012 12:11
  • Jaaaaa! Vielen Dank für die Antwort. Hatte exakt das selbe Problem mit haru. Hat auch gleich geklappt nachdem das Marshalling richtig genutzt wurde :)
    Freitag, 2. Dezember 2016 14:57
  • Vielen Dank. Hat mir sehr geholfen.
    Dienstag, 24. Januar 2017 14:47