[gelöst] pin_ptr und BadImageFormat Exception



  • Hi,

    Ich hab ne dll Assembly in C++/CLI die mir ein paar OpenGL Aufrufe für eine C# Anwendung wrapped. Von beidem hab ich ne x86 und x64 Variante.

    In der x64 Variante läuft alles wie geschmiert aber die x86 Variante crashed mit einer BadImageFormat Exception und ich komm nicht drauf warum. Ich hab die x86 dll mit corflags.exe gecheckt und es sieht so aus als ist das 32Bit Flag im Header der dll nicht gesetzt. Die dll wird aber mit /MACHINE:X86 gebuildet und die exe (definitiv 32bit) führt auch Code aus der dll aus (ich kann sogar mit dem Debugger rein).
    Aber an einem gewissen Punkt fliegt mir auf einmal BadImageFormat um die Ohren.
    Ich denke ich konnte das Problem eingrenzen. Es crashed immer sobald die C# Anwendung folgenden Code aufruft:

    generic<class T>
        where T : value class
      public ref class VertexBuffer : public Buffer
      {
        ...
    
        VertexBuffer(array<T>^ data, Usage usage)
        {
          ...
          glBindBuffer(GL_ARRAY_BUFFER, id);
          pin_ptr<void> ptr = &(data[0]);
          glBufferData(GL_ARRAY_BUFFER,
                       data->GetLength(0) * sizeof(T),
                       ptr,
                       static_cast<GLuint>(usage));
          ...
        }
    
        ...
      };
    

    Ich hab noch ein paar andre ähnliche Stellen und es crashed sobald ich irgendwas davon aufrufe. Ich denke mal es könnte was mit dem pin_ptr da zu tun haben, aber was?

    Es crashed übrigens schon im C# Code an der Stelle wo der Aufruf steht, er kommt erst gar nicht in die dll rein.

    Ich hab schon alles mögliche versucht, die ganze Solution neu gemacht um sicherzugehen dass es nicht von irgendwelchen kaputten Settings ausgelöst wird, aber ohne Erfolg.

    Ich hoffe irgendwer kann mir helfen...



  • Ich vermute, dass er versucht die Falsche DLL zu laden.

    Verifiziere dass die EXE als x86 bzw. x64 markiert ist und nicht als Any!



  • Das war natürlich das erste was ich gemacht hab, die exe ist definitiv x86, sie wird mit /platform:x86 gebuildet und hat das 32Bit Flag im PE Header gesetzt, außerdem wird ein 32bit Prozess erzeugt.
    Und es wird auch die "richige" (aus dem x86 Ordner) dll geladen ich hab das natürlich auch schon überprüft indem ich mir mit Reflection die Liste der geladenen Assemblies angeschaut habe. Und wenn es die falsche dll wäre würde es ja auch sofort crashen, die exe ruft aber wie gesagt nachweislich einige Methoden die in der C++/CLI assembly definiert sind auf bevor es crashed.
    Es muss also irgendwie an der dll selbst liegen, ich weis nur wirklich nicht was ich da falsch mache 😕
    Muss man in VC++ die Target Machine außer in den Linkereinstellungen noch irgendwo umstellen, vielleicht für CLI noch wo extra!?



  • In VC++ musst Du eigentlich nur eine neue Platform für x64 bzw. x86 anlegen; dann sind die Einstellungen alle richtig...



  • Genau das hab ich auch gemacht und in C# dann eben die Target Platform auch entsprechend eingestellt, das war eigentlich alles was ich gemacht hab...



  • Kannst Du nicht debuggen!?
    Was kommt da für eine Meldung? Was steht im Output-Window? Was steht in der Ereignis-Anzeige?



  • Natürlich kann ich debuggen, allerdings liefert mir nichts davon hier irgendwie relevante Information, aber zur Sicherheit:

    Exception Details:

    System.BadImageFormatException was unhandled
      Message="Bad IL format."
      Source="GL"
      StackTrace:
           at GL.VertexBuffer`1..ctor(T[] data, Usage usage)
           at SurfaceTwister.Renderer..ctor(IntPtr hwnd) in D:\michael\SurfaceTwister\Renderer.cs:line 55
           at SurfaceTwister.MainWindow..ctor(SurfaceTwister twister) in D:\michael\SurfaceTwister\MainWindow.cs:line 20
           at SurfaceTwister.SurfaceTwister..ctor() in D:\michael\SurfaceTwister\SurfaceTwister.cs:line 13
           at SurfaceTwister.Program.Main() in D:\michael\SurfaceTwister\Program.cs:line 18
           at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException:
    

    Output Window (das wesentliche, GL.dll is die besagte dll):

    'D:\michael\SurfaceTwister\bin\x86\Debug\GL.dll', Symbols loaded.
    'SurfaceTwister.vshost.exe' (Managed): Loaded 'C:\Windows\WinSxS\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.4148_none_2a4cbfc25558bcd3\msvcm90d.dll', Symbols loaded.
    A first chance exception of type 'System.BadImageFormatException' occurred in SurfaceTwister.exe
    'SurfaceTwister.vshost.exe' (Managed): Loaded 'C:\Windows\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    


  • Danke für deine Mühe, ich hab dank einem Hiweis in einem IRC channel endlich eine Lösung gefunden. Das Problem war in der Tat der pin_ptr. Man sollte offenbar niemals etwas als void pinnen (ich frag mich ja grad wie ich da überhaupt drauf gekommen bin). mit pin_ptr<T> funktionierts jetzt auch mit x86...



  • Das kann ich aber so nicht nachvollziehen...
    Da muss noch was anderes passiert sein...



  • Nein das wars. Mit pin_ptr<void> -> crash, mit pin_ptr<T> -> alles lauft...


Anmelden zum Antworten