none
Fehler bei Ausgabe mittels fprintf aus DLL heraus RRS feed

  • Frage

  • Wenn ich eine DLL erstelle, die ggf. ausschließlich aus der folgenden einfachen Funktion besteht,

    #include <stdio.h>
    void TestPrintfStdout(void )
    {
        fprintf(stdout, "Hello World");
    }

    und diese Funktion von einem Console-Programm aus aufgerufen wird (das wiederum aus nichts anderem als dem Aufruf dieser Funktion besteht), gibt es in allen VS-Versionen von 2005 bis 2015 in den Debug-Runtimes (/MTd, /MDd) einen Absturz oder eine "Assertion failed"-Meldung. Ausnahme: Wenn sowohl die DLL als auch das aufrufende Programm mit /MDd erstellt wurden, geht es glatt.

    Allgemeiner gilt dies für Text-Ausgabe in irgendeinen als FILE* übergebenen Stream:

    #include <stdio.h>
    void TestPrintf(FILE *TestFile)
    {
        fprintf(TestFile, "Hello World");
    }

    Die spezifischen Meldungen variieren je nach Kombination von Runtime für die DLL und das aufrufende Programm. Auch zwischen den VS-Versionen gibt es Unterschiede: VS2005 etwa stürzt ab, bevor es zu irgendeiner Ausgabe kommt. VS2015 erstellt erst die korrekte Ausgabe und bleibt dann mit einem Fehler hängen. Die häufigste Meldung in VS2015 ist:

    Debug assertion failed
    File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cppLine: 980Expression: __acrt_first_block == header

    Alternativ gibt es noch:

    Line: 892Expression: is_block_type_valid(header->_block_use)

    und

    Line: 888
    Expression: _CrtlsValidHeapPointer(block)

    Ist das ein bekanntes Problem? Mache ich einen dummen Fehler?

    Ich wäre für Hinweise sehr dankbar!


    Samstag, 5. März 2016 09:16

Antworten

Alle Antworten

  • Sowohl DLL als auch EXE müssen mit dem selben Compiler mit den selben Updates/Service Packs übersetzt werden. Du kannst nicht wirklich sagen, wohin/worauf Dein FILE* tatsächlich zeigt. Wenn sich das von einer Version der CRT zur nächsten ändert, knallt es natürlich. Portabilität bezieht sich hier auf Quell-Ebene, nicht auf Binär-Ebene.

    Donnerstag, 10. März 2016 12:19
  • Hallo Martin,

    so wie Rene bereits gesagt hast müssen alle Dlls/Anwendungen mit der gleichen Laufzeitbibliothek (Runtime) kompiliert werden.

    Es ist sogar nicht nur wichtig dass die Anwendungen/Dlls mit der identische Version (also 2010, 2012 etc.) von Visual Studio erstellt werden, sondern teilweise sogar das die Updates in der jeweiligen Visual Studio Version identisch sein müssen.

    Wir hatten das nämlich bei Visual Studio 2010, dass sich die Runtime in einer Version geändert hat und wir aber unsere Programme mit der alten Runtime und die DLLs mit der neuen Runtime kompiliert hatten. Bei der Ausführung und leider auch nicht wirklich reproduzierbar bekamen wir immer so ähnliche Fehlermeldungen/Abstürze wie du die oben bereits genannt hast.


    Gruß
    Rudolf

    "Der Nachteil der Intelligenz besteht darin, dass man ununterbrochen gezwungen ist, dazuzulernen." Georg Bernhard Shaw

    Donnerstag, 10. März 2016 19:23
  • Nun hier wurde schon viel richtiges gezagt zu dem Export von Funktionen aus DLLs.

    Wenn man die Abhängigkeiten zum compiler nicht haben möchte müssen die Funktionen "undecorated" exportiert werden. Dann ist die DLL eigentlich von jeder Sprache nutzbar, seit es C/C++ oder auch Delphi, C++ Builder oder was auch immer.

    Dies hier ist ein netter Artikel wie man eine DLL erstellt, die unabhängig von compiler ist:

    http://www.tutorialspoint.com/dll/dll_writing.htm

    Gerade in Verbindung mit DLLs ist aus meiner sicht das Tool DependencyWalker eigentlich ein muß. Früher war dieses Tool Bestandteil des Windows SDK, leider ist es das aus mir nicht bekannten Gründen seit doch nun einigen Jahren nicht mehr.

    http://dependencywalker.com/


    Best regards

    Bordon

    Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.


    • Bearbeitet Bordon Freitag, 18. März 2016 06:15
    Freitag, 18. März 2016 06:13
  • Hallo René, hallo Rudolf,

    vielen Dank für die hilfreichen Antworten! 

    Dass FILE* je nach Runtime nicht gleich FILE* ist, war mir wirklich nicht bewusst - und erscheint mir auch als eine ziemlich unnötige Verkomplizierung. Meine Hoffnung war nämlich ursprünglich, durch Erstellung einer mit der statischen Runtime verlinkten (und damit auf keine weiteren DLLs außer den Windows-Standard-DLLs zugreifenden) DLL unabhängig zu werden von den verschiedenen Runtime-Versionen. So muss ich wohl dabei bleiben, unseren Kunden pro VS-Version je vier Bibliotheken für die vier möglichen Runtimes zu liefern.

    Ich sollte allerdings ergänzen, dass der Fehler tatsächlich in einem Fall auch bei identischer Runtime auftritt, nämlich dann, wenn sowohl DLL als auch Programm mit /MTd compiliert sind.

    Gruß,

      Martin

    Samstag, 19. März 2016 21:28