[英]How to wrap a raw pointer into a shared_ptr and prevent shared_ptr from deleting the object?
[英]How to get shared_ptr from raw pointer?
我正在做c / c ++混合編程,如下所示:
COMMON.H
#ifdef __cplusplus
typedef opentracing::Span CTraceSpan;
#else
struct CTraceSpan;
typedef struct CTraceSpan CTraceSpan;
#endif
extern "C" CTraceSpan* c_StartServerSpan();
extern "C" CTraceSpan* c_FinishServerSpan(CTraceSpan *span);
trace2c.cpp
extern "C" CTraceSpan* c_StartServerSpan(){
auto server_span = hwtrace::StartServerSpan();
return server_span.get();
}
extern "C" CTraceSpan* c_FinishServerSpan(CTraceSpan *span){
std::shared_ptr<opentracing::Span> s_span(std::move(span));
auto server_span = hwtrace::FinishServerSpan(s_span);
return server_span.get();
}
並在trace.c中
CTraceSpan *span = NULL;
span = c_StartClientSpan();
c_FinishClientSpan(span);
當我運行項目時,出現錯誤:
分段故障(核心已轉儲)
下面的問題說不能從原始指針創建shared_ptr,但是我需要將指針形式的c傳遞給c ++,我該怎么辦?
您永遠不要像在這里那樣從普通指針創建shared_ptr:
shared_ptr<ParticleEmitter>(&e)
這將嘗試釋放兩次粒子發射器。 一次,包含ParticleEmitter對象的向量超出范圍,而一次,shared_ptr超出范圍。
下面的問題說,不能從原始指針創建shared_ptr
通常,該特定答案是錯誤的(盡管在特定情況下是正確的)。 您可以從原始指針創建共享指針。 您只是無法從不擁有該對象的指針創建共享指針。
但是我需要將指針形式的c傳遞給c ++,我該怎么辦?
這取決於。 指定對象是如何分配的? 是否需要手動取消分配(即是否動態分配)? 什么時候應該(並且什么時候不能)將其釋放? 誰應該負責釋放(C或C ++)? 應該如何釋放它(應該直接取決於它的分配方式)?
如果對象是靜態或自動的,則無需執行任何特別操作。
如何從原始指針[從C]獲取shared_ptr?
假設對象是使用malloc
在C中分配的,並已分配給負責釋放的C ++代碼,則如下所示:
std::shared_ptr<CTraceSpan> s_span(span, std::free);
分配一些東西,並推卸弄清楚如何將其分配給客戶端代碼的責任,通常是不良的API設計。 因此,對於分配某些東西的每個函數,通常C API都會有一個釋放函數,該函數允許客戶端與釋放細節分離。 當分配的對象本身具有指針動態內存時,這尤其重要。
假設在這種情況下, deallocate_ctrace_span
是這樣的釋放函數:
std::shared_ptr<CTraceSpan> s_span(span, deallocate_ctrace_span);
這么說,看來您的指針實際上不是在C中分配的,而是在C ++中分配的。 您的示例還不完整,還不清楚您打算如何使用共享指針。
shared_ptr
用於共享對象的所有權。 如果它已經由其他人擁有和管理,則可以將引用或非擁有指針傳遞給該對象。
如果所有權確實是共享的,則可以將“ shared_ptr
”存儲在“保存ParticleEmitter的向量”中,然后傳遞該shared_ptr
副本,以便最后一個用戶處理刪除。
如果由於這些CTraceSpan
存在shared_ptr
,則無法從原始指針創建新的shared_ptr
。 否則,您將對CTraceSpan
具有兩個所有權關系,並且在其中之一釋放CTraceSpan
之后將發生不確定的行為。
c_FinishServerSpan
的實現將不得不去找到一個現有的 std::shared_ptr<CTraceSpan>
,以便它的基礎指針等於span
。
static std::map<CTraceSpan*, std::shared_ptr<CTraceSpan>> spans;
extern "C" CTraceSpan* c_StartServerSpan(){
auto server_span = hwtrace::StartServerSpan();
spans[server_span.get()] = server_span;
return server_span.get();
}
extern "C" CTraceSpan* c_FinishServerSpan(CTraceSpan *span){
auto s_span = spans.at(span);
// spans.erase(span) ?
auto server_span = hwtrace::FinishServerSpan(s_span);
spans[server_span.get()] = server_span;
return server_span.get();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.