2009-07-06 8 views
2

사람들이 플러그인을 제공하여 기능을 확장 할 수있게 해주는 응용 프로그램을 작성했습니다. 이러한 플러그인은 프레임 워크가 런타임 중에 선택하는 DLL 파일로 배포됩니다. 각 플러그인은 객체를 생성하기 위해 응용 프로그램의 수명 동안 여러 번 호출되는 팩토리 기능을 갖추고 있습니다. 지금까지는 이러한 객체에 대한 소유권 문제를 처리하기 위해 반환 된 객체에 대한 간단한 계산 공유 포인터를 사용하여 마지막 참조가 제거 될 때마다 객체가 삭제되도록했습니다.DLL 메모리 관리자 믹스

그러나이 문제는 Windows에서 충돌이 발생하는 경향이 있습니다. 그 이유는 객체가 플러그인 DLL에서 new'ed되었지만 나중에 주 응용 프로그램에서 삭제 된 공유 포인터에 대한 deref() 호출로 인해 발생하기 쉽기 때문입니다. AFAIK이 malloc/free mixup은 Windows에서 no-no입니다.

내 현재 해결책은 deref()가 'delete this;'를 호출하지 못하도록하는 것입니다. 직접적이 아니라 'release();' 함수는 플러그인에 의해 구현되어야하며 'delete this;'를 호출합니다. 그러나 각 플러그인이이 사소한 기능을 구현해야한다는 것은 매우 짜증이납니다. 필자는 작성자가 사용하는 편리한 매크로 플러그인을 제공함으로써 지금까지이 문제를 해결했습니다. 누구에게 대체 아이디어가 있을지 모릅니다.

지금까지 나의 접근 방식은 플러그인에서 제공되는 모든 객체가 플러그인에 할당되고 거기에서 릴리스된다는 것입니다. 물론 다른 방법으로는 모든 메모리를 주 응용 프로그램에 할당 할 수 있습니다 (malloc과 같은 기능을 필요에 따라 호출 할 수있는 플러그인에 추가). 이 문제는 플러그인 작성자가별로 편리하지 않다고 생각합니다.

이 문제에 대한 다른 관점에도 관심이 있습니다.

UPDATE : 난 그냥 내가 new 연산자를 구현할 수 있으며,이를 new'ing하고 항상 기능을 발생합니다 delete'ing하는 것은으로 호출하도록 연산자, 플러그인에 의해 반환 된 개체의 base class에 삭제하는 것이 실현 동일한 모듈 (모든 할당과 프리가 플러그인이나 프레임 워크에서 수행되도록).

답변

3

두 가지 해결책이 있습니다. 솔루션 1은 "더 많은 것을 공유합니다"- 양측이 동일한 CRT DLL (MSVC에서/MD 또는/MDd)을 사용하면 DLL 경계를 넘어서 새/삭제를 이동할 수 있습니다. 솔루션 2는 "덜 공유"합니다. 각 DLL에 자체 C++ 힙이 있고 DLL 경계에서 새/삭제가 분할되지 않도록하십시오.

2

DLL 코드가 개체를 할당하는 책임이있는 경우 DLL 코드도 개체를 해제해야합니다. 나는 당신의 문제가 참조 카운팅과 "삭제"와 더 있다고 생각합니다. 그 경로를 가고 싶다면 COM 객체로 객체를 구현하는 것이 어떻습니까? 이것은 COM이 해결하도록 고안된 주요 문제들 중 하나입니다!

4

메모리가 하나의 DLL에 할당되지 않고 또 다른 DLL에서 배포되지 않도록하는 가장 쉬운 방법은 다음과 같습니다. 플러그인에서 반환 된 객체의 기본 클래스에 operator newoperator delete을 다시 구현합니다. 이러한 함수의 구현에서 'alloc'및 'free'함수 (플러그인을로드 할 때 기본 응용 프로그램에서 전달 된 함수)를 호출하십시오. 그렇게하면 플러그인은 'new'와 'delete'를 계속 사용할 수 있지만 메모리는 실제로 메인 애플리케이션에 할당되고 해제됩니다.

+0

기본 클래스의 new 연산자와 delete 연산자를 다시 구현하면 메모리를 사용하지만 해당 클래스 내에서 할당이 수행되면 어떨까요? 플러그인 공급자가 문자열 멤버를 추가하면 dll에 할당됩니다. 그러나 당신이 당신 편에서 객체를 지우면, 그 문자열은 당신 편에서 파괴 될 것입니다, 그렇지 않습니까? obj * Create() 및 Destroy (obj *) 전역 함수 또는 AddRef() 및 Release() 인스턴스를 제공합니다. 나에게 훨씬 안전 해. – eran

+0

@eran이 의견은 약 3.5 년 늦었지만 귀하의 우려를 이해하고 있는지 확신 할 수 없습니다.기본 클래스에서'operator new'와'operator delete'를 재정의하면 파생 클래스 내에서 사용될 경우 해당 연산자도 사용됩니다. 예 : http://ideone.com/cdNZMp 커스텀'new' /'delete' 구현에 대한 두 번의 호출을 보여줍니다. 한 쌍은'Derived :: f' 내에서'return new Derived;에 의해 발생합니다. –

+0

예제 코드는'operator new'가 다시 구현 된 클래스의 인스턴스를 생성하므로 어쨌든 커버됩니다. 내 관심사는 기본 new를 사용하는 필드를 가진 파생 된 클래스라고 생각합니다. 해당 클래스의 '새'는 귀하의 게재 위치에 포함되지 않습니다. 그러나 이제 나는 이것을 다시 읽었으며, 나는 틀렸다고 생각한다. 클래스 내의 모든 메모리 관리는 기본 클래스에 의해 파괴 된 기본 클래스에 의해 생성되는 것이 안전하며, 파생 클래스에 의해 생성되는 것은 파생 클래스에 의해 파괴됩니다. – eran