2009-12-24 2 views
10

부스트 공유 포인터를 반환하고 매개 변수로 사용하는 DLL을 C++로 개발할 수 있습니까?DLL 인터페이스에서 boost :: shared ptr을 사용해도 되나요?

그럼이 같은 함수를 내보내시겠습니까? 특별한에서

1.) boost::shared_ptr<Connection> startConnection(); 
2.) void sendToConnection(boost::shared_ptr<Connection> conn, byte* data, int len); 

는 : DLL 경계 또는에서 참조 횟수 작업이 요구 사항은 EXE 것이 있는가와 같은 런타임을 사용하여 DLL?

의도는 개체 소유와 관련된 문제를 극복하기위한 것입니다. 그래서 dll과 exe가 더 이상 그것을 참조하지 않을 때 객체는 삭제됩니다.

답변

10

Effective C++ (3rd Edition)의 Scott Meyers에 따르면 shared_ptrs는 dll 경계에서 안전합니다. shared_ptr 객체는 그것을 생성 한 dll에서 소멸자에 대한 포인터를 유지합니다. 항목 그는 주장한다 (18)에 그의 책에서

, 교차 DLL 문제 " (TR1)의 특히 좋은 기능 :: shared_ptr의는 자동으로 다른 잠재적 인 클라이언트 오류의를 제거하기 위해 당 포인터 Deleter가 를 사용한다는 것입니다" " 동적으로 연결된 라이브러리 (DLL)에서 새를 사용하여 개체가 만들어 지지만 다른 DLL에서 삭제 될 때이 문제가 발생합니다. 많은 플랫폼에서 이러한 교차 DLL 새/삭제 쌍은 런타임에 오류를 발생시킵니다. tr1 :: shared_ptr은 기본 삭제 자 이 tr1 :: shared_ptr이 만들어진 동일한 DLL에서 삭제를 사용하기 때문에 문제가 발생하지 않도록합니다. "

Tim Lesher는 흥미로운 문제를 가지고 있는데, 그가 언급 한 것은 here입니다. 마지막으로 shared_ptr이 범위를 벗어나기 전에 shared_ptr을 만든 DLL이 언로드되지 않도록해야합니다. 나는 대부분의 경우에 이것이 당신이 볼 필요가있는 것이 아니라, 느슨하게 결합 될 dll을 생성한다면 shared_ptr을 사용하지 말 것을 권고한다.

또 다른 잠재적 인 단점은 부스트 ​​라이브러리의 호환 버전으로 양면이 만들어 졌는지 확인하는 것입니다. Boost의 shared_ptr은 오래 동안 안정되어있었습니다. 적어도 1.34부터 tr1과 호환되었습니다.

+2

주의 : 정적 CRT를 연결하는 경우 문제가 발생합니다. CRT에 정적으로 링크 된 각 모듈은 자체 힙을 가져옵니다. 모든 모듈이 DLL CRT에 링크하면 모두 힙을 공유합니다. – Zac

2

DLL은 일반적으로 리소스를 소유하지 않습니다. 리소스는 DLL을 사용하는 프로세스가 소유합니다. 아마도 일반 포인터를 반환하는 것이 더 나을 것입니다. 그러면 포인터를 호출 측의 공유 포인터에 저장합니다. 그러나 더 많은 정보가 없으면 이것에 대해 100 % 확신 할 수 없습니다.

4

제 생각에는 이것이 표준에없고 라이브러리에서 제공하는 객체/메커니즘이 아니라면 라이브러리에 대한 인터페이스의 일부가되어서는 안됩니다. 참조 카운팅을 위해 자신 만의 객체를 만들 수 있으며, 아마도 부스트를 사용하지만 인터페이스에 명시 적으로 노출되어서는 안됩니다.

2

dll 인터페이스에서 원시 포인터를 노출 할 때주의해야 할 사항. 그것은 당신이 공유 dll CRT를 사용하도록 강요합니다. 하나의 CRT에 할당 된 메모리는 다른 CRT에서 할당 해제 될 수 없습니다. 모든 모듈 (dll의 & exe)에 공유 dll CRT를 사용하면 CRT와 세계가 붕괴 될 것입니다. 그렇다면 모두 동일한 힙을 공유합니다.

해당 문제 외에도 허용 된 답변에 동의합니다. 생성 팩토리는 클라이언트 코드에 대해 소유권 &주기 관리를 정의하지 않아야합니다.

+0

exe와 dll이 공유 dll CRT를 사용하는 것을 어떻게 보장 할 수 있습니까? 이것에 대한 컴파일러 플래그는 무엇입니까? –

0

아니요.

boost::shared_ptr<T>의 레이아웃이 DLL 경계의 양쪽에서 같지 않을 수 있습니다. (레이아웃은 컴파일러 버전, 패킹 pragma 및 기타 컴파일러 옵션, 그리고 Boost 소스 코드의 실제 버전의 영향을받습니다.)

"표준 레이아웃"(C++ 11의 새로운 개념, 이전의 "POD = 평범한 구 데이터"개념) 유형은 별도로 작성된 모듈간에 안전하게 전달할 수 있습니다.

관련 문제