2014-11-27 1 views
0

리플렉션을 사용하여 플러그인의 함수를 호출하는 플러그인 시스템을 만들었습니다. 플러그인은 사용할 IPlugin 인터페이스를 구현해야합니다. 플러그인 인스턴스가 다음 코드로 생성 된 플러그인을 사용하는 응용 프로그램에서 : 좀 unmannaged DLL의 사용하는 플러그인을 만들었습니다리플렉션을 사용하여 dll 함수를 호출 할 때 보호 된 메모리를 읽거나 쓰려고 시도했습니다.

Assembly currentAssembly = Assembly.LoadFrom(startInfo.PluginAssemblyPath); 
    Type[] types = currentAssembly.GetTypes(); 
    IPlugin pluginInstance = null; 

    foreach (Type type in types) 
    { 
     if (type.FullName == startInfo.PluginTypeName) 
     { 
      pluginInstance = (IPlugin)Activator.CreateInstance(type); 
     } 
    } 

    if (pluginInstance == null) 
    { 
     throw new Exception("Plugin loader error: Could not instantiate plugin: " + startInfo.ToString());  } 

    return pluginInstance; 

. 테스트 솔루션에서 IPlugin 인터페이스 함수를 호출하면 모든 것이 잘 동작합니다. 그러나 위의 코드에서 만든 플러그인 인스턴스를 통해 플러그인을 호출 할 때 System.AccessViolationException이 발생합니다. unmannaged dll에서 함수를 호출 할 때 보호 된 메모리 오류를 읽거나 쓰려고 시도했습니다.

unmannaged dll은 제 3 자에 의해 만들어진 C++ dll입니다. 네이티브 코드 디버깅을 사용하려고했지만 .pdb 파일이 없습니다.

왜 이런 일이 발생했는지 나는 잘 모르겠습니다. 반성 때문입니까? 아니면 다른 원인이있을 수 있습니까?

편집 : 나는 unmannaged 기능을 볼 수있는 스택에서 가 호출되는 다음 _xLib 함수를 호출 할 때

[MarshalAs(UnmanagedType.LPStr)] 
private readonly StringBuilder sb = new StringBuilder(256); 

[DllImport("x.dll", EntryPoint = "xLib")] 
static extern int _xLib(int a1, int a2, int a3, int a4, int a5, int a6, [Out]StringBuilder str); 

예외가 발생합니다.

편집 :이 _xLib의 어딘가에는 다음 함수를 호출 기능 : 타 DLL에 다음과 같이 정의된다

handle = x_Open(); 

: 핸들에 아무것도 즉시

DllExport x_Handle *x_Open(); 

입니다 다음과 같이 사용 :

"%s", handle->x.string 

예외가 발생합니다. 여전히 테스트 프로젝트에서 작동하는 이유를 이해하지 못하고 플러그인으로 앱에서 사용할 때가 아닙니다.

+0

적어도 스택 추적을 제공하십시오. 호출중인 원시 함수의 이름. – leppie

+1

물론 디버거가 필요합니다. 프로젝트 + 속성, 디버그 탭에서 "네이티브 코드 디버깅 사용"옵션을 선택합니다. –

+0

@Hans Passant 그랬지만 디버거에는 가지고 있지 않은 .pdb 파일이 필요합니다. –

답변

0

어떤 집중 디버깅을 한 후에는 위반의 원인이 된 잘못된 주소. 주소가 틀린 원인은 x_open 함수가 LoadLibraryA 함수가있는 다른 dll을로드했기 때문입니다. 이 dll은 실행 파일과 동일한 디렉토리에 없으므로 찾을 수 없습니다.

이 마지막 dll의 디렉토리를 환경 경로에 추가하여 해결했습니다.

0

아마도 비 관리 코드가 상호 작용할 수 있도록 StringBuilder을 고정해야 할 수 있습니다.

고정 된 개체는 이동이 허용되지 않는 개체입니다. 일반적으로 가비지 수집기는 모든 개체를 "하나 이상의 클러스터"로 이동한다는 점에서 메모리를 압축합니다. 이것은 자유 공간의 큰 덩어리를 만드는 것입니다.

이것은 기본적으로 다른 사람 (외부)이 개체의 메모리 주소에 대한 포인터를 가지고있는 경우 이는 개체가 이동함에 따라 임의의 콘텐츠를 가리킬 수 있음을 의미합니다.

개체를 고정하면 GC에 NOT MOVE IT가 표시됩니다. 이것은 일반적으로 쓸모가 없으며 PInvoke를 사용할 때처럼 포인터로 작업 할 때만 의미가 있습니다 ... 그리고 StringBuilder 인스턴스에 대한 포인터를 볼 수 있습니다 function

+0

마샬 러는'StringBuilder' 인스턴스를 처리하는 방법을 알고 있습니다. 고정되어 있지 않은 코드가 호출이 완료된 후에도 데이터에 대한 포인터를 유지하지 않는 한 고정시킬 필요가 없습니다. 그렇다면 관리되지 않는 메모리 블록을 할당하고 'StringBuilder'를 무기한 고정하지 않습니다. –

+0

@ 제론 당신이 옳다고 생각합니다. 나는 시도했다 : 'GCHandle sbHandle = GCHandle.Alloc (sb);' 그러나 그것은 도움이되지 않는다. –

관련 문제