簡體   English   中英

如何從原始指針獲取shared_ptr?

[英]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:

 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM