приложение выходит (без исключения) при обращении к 64-битной DLL из C # - PullRequest
9 голосов
/ 23 ноября 2011

Я скомпилировал lzo2.dll 64 бит и теперь хочу использовать его в программе на C #:

Я использую следующий класс для тестирования (аналогичный код работает для 32bit lzo.dll):

[DllImport("lzo2.dll")]
private static extern string lzo_version_string();
static void Main(string[] args)
{
    try
    {
        if (Environment.Is64BitProcess)
        {
            Console.WriteLine(lzo_version_string());//application exits here, no exceptions caught 
        }                
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
    Console.ReadLine();
}

В указанном месте происходит сбой приложения, поэтому я вытащил windbg и вот что получилось: (извините за многословие)

0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\e0e5fbe72e8813a135fc878ff32b4bee\mscorlib.ni.dll
*** WARNING: Unable to verify checksum for Lzo64.exe
GetPageUrlData failed, server returned HTTP status 404
URL requested: http://watson.microsoft.com/StageOne/Lzo64_exe/1_0_0_0/4eccdc93/ntdll_dll/6_1_7601_17514/4ce7c8f9/80000003/000c40bf.htm?Retriage=1

FAULTING_IP: 
ntdll!RtlReportCriticalFailure+2f
00000000`77a240bf cc              int     3

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 0000000077a240bf (ntdll!RtlReportCriticalFailure+0x000000000000002f)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 1
   Parameter[0]: 0000000000000000

FAULTING_THREAD:  0000000000001c90

PROCESS_NAME:  Lzo64.exe

ERROR_CODE: (NTSTATUS) 0x80000003 - {EXCEPTION}  Breakpoint  A breakpoint has been reached.

EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are invalid

EXCEPTION_PARAMETER1:  0000000000000000

MOD_LIST: <ANALYSIS/>

NTGLOBALFLAG:  70

APPLICATION_VERIFIER_FLAGS:  0

MANAGED_STACK: 
(TransitionMU)
000000000054E670 000007FEF1F3BF6C mscorlib_ni!System.StubHelpers.CSTRMarshaler.ClearNative(IntPtr)+0x3c
000000000054E730 000007FF00140319 Lzo64!DomainBoundILStubClass.IL_STUB_PInvoke()+0x14031a
000000000054E840 000007FF00140181 Lzo64!Lzo64.Program.Main(System.String[])+0x61
(TransitionUM)

MANAGED_STACK_COMMAND:  _EFN_StackTrace

LAST_CONTROL_TRANSFER:  from 0000000077a24736 to 0000000077a240bf

BUGCHECK_STR:  APPLICATION_FAULT_WRONG_SYMBOLS_CALL

PRIMARY_PROBLEM_CLASS:  WRONG_SYMBOLS_CALL

DEFAULT_BUCKET_ID:  WRONG_SYMBOLS_CALL

STACK_TEXT:  
00000000`0054e3d0 00000000`77a24736 : 00000000`00000002 00000000`00000023 00000000`0054e6a8 00000000`00000003 : ntdll!RtlReportCriticalFailure+0x2f
00000000`0054e4a0 00000000`77a25942 : 000007fe`f1533de8 000007fe`f1533de8 00000000`0054ea10 00000000`0054e8a8 : ntdll!RtlpReportHeapFailure+0x26
00000000`0054e4d0 00000000`77a275f4 : 00000000`005d0000 00000000`00000000 00000000`00000000 00000000`0064e560 : ntdll!RtlpHeapHandleError+0x12
00000000`0054e500 00000000`779cdcb7 : 000007fe`faab7b68 00000000`005d0000 000007fe`faab7b68 000007fe`f2d85000 : ntdll!RtlpLogHeapFailure+0xa4
00000000`0054e530 000007fe`fe3e8e56 : 00000000`0054e900 000007fe`faab7b68 00000000`f2734dd5 00000000`00000000 : ntdll! ?? ::FNODOBFM::`string'+0x10c7c
00000000`0054e5b0 000007fe`f27319c2 : 000007fe`faab7b68 0000a965`d9ebab11 000007fe`faab7b68 00000000`00000004 : ole32!CoTaskMemFree+0x36
00000000`0054e5e0 000007fe`f1f3bf6c : 000007fe`faab7b68 00000000`0054ea10 0000a965`d9ebab11 000007fe`f2dbd2c0 : clr!DoNDirectCallWorker+0x62
00000000`0054e670 000007ff`00140319 : 00000000`00000000 000007ff`000240f0 00000000`0054ea10 00000000`0054e8a8 : mscorlib_ni+0xa8bf6c
00000000`0054e730 000007ff`00140181 : 00000000`00000001 00000000`0054eaa0 00000000`0054e900 000007fe`f2734dd5 : 0x7ff`00140319
00000000`0054e840 000007fe`f2759714 : 00000000`02c31a58 00000000`0054eaa0 00000000`0054e900 000007fe`f2734dd5 : 0x7ff`00140181
00000000`0054e8a0 000007fe`f2759829 : 000007ff`00024138 00000000`00000001 00000000`00000000 00000000`00000000 : clr!CallDescrWorker+0x84
00000000`0054e8f0 000007fe`f27598a5 : 00000000`0054ea08 00000000`00000001 00000000`0054ea10 00000000`0054ebf0 : clr!CallDescrWorkerWithHandler+0xa9
00000000`0054e970 000007fe`f28f6651 : 00000000`00000000 00000000`0054ebf8 00000000`00000001 000007fe`f14b1a32 : clr!MethodDesc::CallDescr+0x2a1
00000000`0054eba0 000007fe`f28f6788 : 00000000`0064e560 00000000`0064e560 00000000`00000000 00000000`00000000 : clr!ClassLoader::RunMain+0x228
00000000`0054edf0 000007fe`f28f653e : 00000000`0054f3f0 00000000`00000200 00000000`0065afa0 00000000`00000200 : clr!Assembly::ExecuteMainMethod+0xac
00000000`0054f0a0 000007fe`f2915e56 : 00000000`00000000 00000000`01280000 00000000`00000000 00000000`00000000 : clr!SystemDomain::ExecuteMainMethod+0x452
00000000`0054f650 000007fe`f2915d73 : 00000000`01280000 00000000`00000000 00000000`00000000 00000000`00000000 : clr!ExecuteEXE+0x43
00000000`0054f6b0 000007fe`f2906c6d : 00000000`0064e560 ffffffff`ffffffff 00000000`00000000 00000000`00000000 : clr!CorExeMainInternal+0xc4
00000000`0054f720 000007fe`f9d03309 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`0054f708 : clr!CorExeMain+0x15
00000000`0054f760 000007fe`f9e15b21 : 000007fe`f2906c58 000007fe`f9d032c0 00000000`00000000 00000000`00000000 : mscoreei!CorExeMain+0x41
00000000`0054f790 00000000`773f652d : 000007fe`f9d00000 00000000`00000000 00000000`00000000 00000000`00000000 : MSCOREE!CorExeMain_Exported+0x57
00000000`0054f7c0 00000000`7798c521 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0xd
00000000`0054f7f0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d


STACK_COMMAND:  .cxr 0000000000000000 ; kb ; dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; ~0s ; kb

FOLLOWUP_IP: 
clr!DoNDirectCallWorker+62
000007fe`f27319c2 41c744240c01000000 mov   dword ptr [r12+0Ch],1

SYMBOL_STACK_INDEX:  6

SYMBOL_NAME:  clr!DoNDirectCallWorker+62

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: clr

IMAGE_NAME:  clr.dll

DEBUG_FLR_IMAGE_TIMESTAMP:  4e1822f4

FAILURE_BUCKET_ID:  WRONG_SYMBOLS_CALL_80000003_clr.dll!DoNDirectCallWorker

BUCKET_ID:  X64_APPLICATION_FAULT_WRONG_SYMBOLS_CALL_clr!DoNDirectCallWorker+62

WATSON_STAGEONE_URL:  http://watson.microsoft.com/StageOne/Lzo64_exe/1_0_0_0/4eccdc93/ntdll_dll/6_1_7601_17514/4ce7c8f9/80000003/000c40bf.htm?Retriage=1

Followup: MachineOwner
---------

Я посмотрел на это, но все еще не могу определить даже намек на проблему. Я полагаю, что он жалуется на символы даже несмотря на то, что трассировка стека выглядит так, как будто у нее есть имена, и, таким образом, дает некоторое значение. Может кто-то намекнуть на то, что может быть проблемой или указать направление, чтобы идти дальше?

Открывается ОК в Обозреватель CFF и Уокер зависимостей.

Похоже, что not является проблемой с самим lzo2.dll, поскольку тестовые приложения, предоставляемые в процессе сборки (lzotest.exe -mlzo COPYING), проходят.

1 Ответ

13 голосов
/ 23 ноября 2011

Нет трассировки стека, но я могу догадаться, вы видите где-то там CoTaskMemFree (). Именно это вызывает маршаллер pinvoke, чтобы освободить строковый буфер, который был возвращен функцией. Проблема в том, что строковый буфер не был выделен CoTaskMemAlloc (). Vista и Windows 7 имеют гораздо более строгий менеджер памяти, они не позволяют программе освобождать память, которую она не выделяла. Он работает на XP, он просто игнорирует неверный указатель буфера.

Функции C, которые возвращают строки, являются проблемой управления памятью. Однако в этом конкретном случае это может сработать, возможно, он возвращает строковый литерал, который не нужно выпускать. Вы должны остановить маршаллера от попытки освободить строку, объявите функцию следующим образом:

[DllImport("lzo2.dll")]
private static extern IntPtr lzo_version_string();

и используйте его так:

IntPtr strPtr = lzo_version_string();
string version = Marshal.PtrToStringAnsi(strPtr);
...