如何从原始指针获取shared_ptr?

How to get shared_ptr from raw pointer?

本文关键字:shared ptr 获取 指针 原始      更新时间:2023-10-16

我正在做 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);

跟踪2c.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();
}

和跟踪.c

CTraceSpan *span = NULL;
span = c_StartClientSpan();
c_FinishClientSpan(span);

当我运行我的项目时,我收到一个错误:

分段故障(核心转储(

下面的问题,说不能从原始指针创建shared_ptr,但是我需要将指针形式C传输到C ++,该怎么办?

使用shared_ptr时的分段错误

您永远不应该像这里那样从普通指针创建shared_ptr:

shared_ptr<ParticleEmitter>(&e)

这会尝试释放粒子发射器两次。一次是作为包含粒子发射器对象的矢量超出范围,一次是作为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欠这些CTraceSpan,则无法从原始指针创建新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();
}

shared_ptr用于共享对象的所有权。如果它已由其他人拥有和管理,则可以将引用或非拥有指针传递给该对象。

如果所有权确实共享的,你可以在"保存粒子发射器的向量"中存储一个shared_ptr,然后传递该shared_ptr的副本,以便最后一个用户处理删除。