관리 된 코드에서 기본 코드를 호출 할 때 도전적인 런타임 오류
-
22-07-2019 - |
문제
First_Layer
VC ++ 6 서비스 팩 6에 Win32 DLL이 작성되었습니다. FirstLayer의 소스 코드에 액세스 할 수는 없지만 관리 코드에서 호출해야합니다. 문제는 Firstlayer가 std :: vector 및 std :: string을 많이 사용하고 이러한 유형을 C# 응용 프로그램으로 직접 마샬링하는 방법이 없다는 것입니다. 아래이 계층의 코드는이 DLL에서 찾을 수있는 내용의 예를 보여줍니다.
Second_layer
내가 생각할 수있는 솔루션은 먼저 VC ++ 6 서비스 팩으로 작성된 또 다른 Win32 DLL을 만드는 것입니다. Sec
Third_Layer
또한 두 번째 레이어의 래퍼로 VC ++ 2005 클래스 라이브러리를 만들었습니다. 이 래퍼는 관리되지 않는 2 학년을 관리 코드로 변환하는 모든 더러운 작업을 수행합니다. 이 레이어를 "Thirdlayer"라고합시다. 아래 그림과 같이이 레이어의 코드는 오류를 보여주기 위해 단순화되어 위에서 언급 한 변환을 수행하지 않습니다.
Fourth_Layer
무엇보다도, 나는 C#2005 콘솔 애플리케이션을 만들어 ThirdLayer를 호출했습니다. 이 C# 콘솔 응용 프로그램을 "Fourthlayer"라고합시다.
호출 시퀀스 요약
Fourthlayer (C#2005) -> ThirdLayer (VC ++ 2005) -> SecondLayer (VC ++ 6) -> FirstLayer (VC ++ 6)
런타임 오류
아래 코드 아래 코드는 오류없이 컴파일/빌드하지만 다음 런타임 오류가 발생합니다.
처리되지 않은 예외 : System.AccessViolationException : 보호 된 메모리를 읽거나 쓰려고 시도했습니다. 이것은 종종 다른 기억이 손상되었음을 나타냅니다. secondlayer.PassDatabackTocaller에서 (2 차 레이어 , stdVectorWrapper*)에서 sample.thirdlayer.passdatabacktocaller ()의 c : project in c : project on going projects test sample thirdlayer thirdlayer.cpp : fourthlayer.program.main (string [] args)의 22 행 C : 프로젝트 프로젝트 test test sample fourthlayer program.cs : 라인 14*
이 오류는 다른 운영 체제에서 Fourthlayer 응용 프로그램이 실행될 때 표시되지 않습니다. 예를 들어 Windows XP의 경우 오류가 없지만 Vista 및 Windows 7과 같은 다른 OS의 경우 오류가 나타납니다.
나는 이것을 일으키는 원인을 이해하지 못한다. 어떤 아이디어? 이것을 수정하기 위해 코드를 수정하려면 어떻게해야합니까?
// Fourth_Layer (C#2005 콘솔 응용 프로그램)
class FourthLayer
{
static void Main(string[] args)
{
ThirdLayer thirdLayer = new ThirdLayer();
thirdLayer.PassDataBackToCaller();
}
}
// Third_Layer (VC ++ 2005 클래스 라이브러리)
public ref class ThirdLayer
{
private:
SecondLayer *_secondLayer;
public:
ThirdLayer();
~ThirdLayer();
void PassDataBackToCaller();
};
ThirdLayer::ThirdLayer()
{
_secondLayer = new SecondLayer();
}
ThirdLayer::~ThirdLayer()
{
delete _secondLayer;
}
void ThirdLayer::PassDataBackToCaller()
{
StdVectorWrapper v;
_secondLayer->PassDataBackToCaller(v);
for (int i=0; i<v.GetSize(); i++)
{
StdStringWrapper s = v.GetNext();
std::cout << s.CStr() << std::endl;
}
}
// Second_Layer- 메인 클래스 (VC ++ 6 Win32 DLL)
class SECOND_LAYER_API SecondLayer
{
private:
FirstLayer *_firstLayer;
public:
SecondLayer();
~SecondLayer();
void PassDataBackToCaller(StdVectorWrapper &toCaller);
private:
void ConvertToStdVectorWrapper(
const std::vector<std::string> &in, StdVectorWrapper &out);
};
SecondLayer::SecondLayer() : _firstLayer(new FirstLayer())
{
}
SecondLayer::~SecondLayer()
{
delete _firstLayer;
}
void SecondLayer::PassDataBackToCaller(StdVectorWrapper &toCaller)
{
std::vector<std::string> v;
_firstLayer->PassDataBackToCaller(v);
ConvertToStdVectorWrapper(v, toCaller);
}
void SecondLayer::ConvertToStdVectorWrapper(
const std::vector<std::string> &in, StdVectorWrapper &out)
{
for (std::vector<std::string>::const_iterator it=in.begin(); it!=in.end(); ++it)
{
StdStringWrapper s((*it).c_str());
out.Add(s);
}
}
// Second_Layer -StdVectorWrapper Class (VC ++ 6 Win32 DLL)
class SECOND_LAYER_API StdVectorWrapper
{
private:
std::vector<StdStringWrapper> _items;
int index;
public:
StdVectorWrapper();
void Add(const StdStringWrapper& item);
int GetSize() const;
StdStringWrapper& GetNext();
};
StdVectorWrapper::StdVectorWrapper()
{
index = 0;
}
void StdVectorWrapper::Add(const StdStringWrapper &item)
{
_items.insert(_items.end(),item);
}
int StdVectorWrapper::GetSize() const
{
return _items.size();
}
StdStringWrapper& StdVectorWrapper::GetNext()
{
return _items[index++];
}
// Second_Layer -STDSTRINGWRAPPER CLASS (VC ++ 6 Win32 DLL)
class SECOND_LAYER_API StdStringWrapper
{
private:
std::string _s;
public:
StdStringWrapper();
StdStringWrapper(const char *s);
void Append(const char *s);
const char* CStr() const;
};
StdStringWrapper::StdStringWrapper()
{
}
StdStringWrapper::StdStringWrapper(const char *s)
{
_s.append(s);
}
void StdStringWrapper::Append(const char *s)
{
_s.append(s);
}
const char* StdStringWrapper::CStr() const
{
return _s.c_str();
}
// First_Layer (VC ++ 6 Win32 DLL)
class FIRST_LAYER_API FirstLayer
{
public:
void PassDataBackToCaller(std::vector<std::string> &toCaller);
};
void FirstLayer::PassDataBackToCaller(std::vector<std::string> &toCaller)
{
std::string a, b;
a.append("Test string 1");
b.append("Test string 2");
toCaller.insert(toCaller.begin(),a);
toCaller.insert(toCaller.begin(),b);
}
해결책
솔루션을 찾았습니다. 기본적으로 두 가지 문제가 있습니다.
문제 1 (FirstLayer와 Secondlayer 사이)
기본적으로 VC ++ 6의 다음 설정은 멀티 스레드입니다. 이 설정은 FirstLayer와 SecondLayer 모두에 대해 멀티 스레드 DLL로 변경해야합니다. 두 가지 모두 작동하기 위해이 새로운 설정과 재 컴파일해야합니다.
프로젝트-> 설정-> C/C ++ Tab-> 카테고리 : 코드 생성-> 런타임 라이브러리 사용-> 멀티 스레드 DLL
문제 2 (Secondlayer와 Thirdlayer 사이)
내가 쓴 stdstringwrapper 및 stdvectorwrapper 클래스는 딥 카피를 구현하지 않습니다. 따라서 딥 카피를 구현하기 위해 STDSTRINGWRAPPER 및 STDVECTORWPRAPPER 클래스에 다음을 추가하는 것입니다.
- 생성자 복사
- 과제 연산자
- 해체 조치
편집하다: 문제 2에 대한 대체 솔루션
더 나은 솔루션은 사용하는 것입니다 clone_ptr std :: 벡터에 포함 된 모든 요소와 std :: 벡터 자체에 대해. 이는 카피 생성기, 할당 연산자 및 해체가 필요하지 않습니다. 그래서 stdvectorwrapper 클래스 내에서 당신은 그것을 다음과 같이 선언합니다.
clone_ptr< std::vector< clone_ptr< StdStringWrapper > > > _items;