我正在使用unique_ptr管理一些资源,以便在任何情况下安全销毁,等等.
void do_something(BLOB* b);
unique_ptr<BLOB> b(new_BLOB(20));
Run Code Online (Sandbox Code Playgroud)
是&*不是变得更糟?例如
do_something(&*b);
Run Code Online (Sandbox Code Playgroud)
要么
do_someting(b.get());
Run Code Online (Sandbox Code Playgroud)
两者似乎都有效.
TLDR:Strands序列化在完成处理程序之间共享的资源:如何防止ssl :: stream实现对并发读写请求(stream :: ssl不是全双工)对SSL上下文(内部使用)的并发访问?请记住,strand仅序列化完成处理程序调用或读/写请求的原始队列。[感谢sehe帮助我更好地表达了这一点]
我花了整整一天的时间阅读有关ASIO,SSL和链的信息;主要在stackoverflow上(其中有一些非常详细且表达明确的解释,例如,为什么在使用boost :: asio时为什么需要每个连接使用绞链)和Boost文档;但有一点尚不清楚。
显然,链可以序列化同一链中的回调,因此也可以序列化对那些链共享的资源的访问。
但是在我看来,boost :: asio :: ssl :: stream的问题不在完成处理程序回调中,因为不是在SSL上下文上同时运行的回调,而是ssl :: stream的实现。 。
我不能确定在调用async_read_some和async_write_some时使用strands或在完成处理程序中使用strands会阻止io引擎同时在不同线程中的SSL上下文上运行。
显然,在调用async_read_some或async_write_some时使用绞合线将意味着不能同时在同一队列中进行读取和写入,但是我看不到如何阻止内部实现同时在不同的位置执行读取和写入操作如果封装的tcp :: socket同时准备好进行读取和写入,则将线程化。
在此问题的最后一个答案末尾的注释增强了asio-来自一个线程的SSL async_read和async_write声称并发写入ssl :: stream可能会出现段错误,而不仅仅是交错,这表明该实现未采取必要的锁定措施来防范并发访问。
除非实际的延迟套接字写操作绑定到将其排队的线程/线程(我看不到它是正确的,否则会破坏工作线程的有用性),否则我如何确定可以将读取排队并在同一ssl :: stream上进行写入,或者那样的方式可能是?
也许async_write_some立即使用SSL上下文处理所有数据,以生成加密数据,然后成为普通套接字写入,因此可以与同一链上的读取完成处理程序不冲突,但这并不意味着在完成处理程序在链上排队之前,它不会与内部实现套接字读取和解密冲突。不必介意可能发生的透明SSL会话重新协商...
我从中注意到:为什么在使用boost :: asio时为什么每个连接都需要链?“组合操作是唯一的,因为对流的中间调用是在处理程序的链中(如果存在的话)而不是在其中发起组合操作的链中调用。” 但是我不确定我指的是“流的中间调用”。这是否意味着:“该流实现中的任何后续处理”?我怀疑不是
最后,为什么,为什么?为什么ssl :: stream实现不使用没有冲突的廉价futex或其他锁?如果遵循绞线规则(隐式或显式),则成本几乎不存在,但否则将提供安全性。我问,因为我刚刚将Sutter,Stroustrup和其他产品的宣传转移了,C ++使一切变得更好,更安全,因此使用ssl :: stream似乎很容易遵循某些咒语,但几乎无法知道您的代码是否真正安全。
这不是关于模板构造函数的问题的重复,甚至不是调用继承的模板构造函数.
它具体是关于在unique_ptr <...,...>模板的类实例(?)的子类中调用继承的构造函数.
为了使代码更容易理解,我using在这个例子中使用:
using B = std::unique_ptr<int *, decltype(&::free)>;
class int_ptr : public B {
int_ptr(int *b) : B(b, &::free) { };
};
Run Code Online (Sandbox Code Playgroud)
但编译失败:
In constructor 'int_ptr::int_ptr(int*)':
error: no matching function for call to
'std::unique_ptr<int*, void (*)(void*) throw ()>::unique_ptr(int*&, void (*)(void*) throw ())'
int_ptr(int *b) : B(b, &::free) { };
^
Run Code Online (Sandbox Code Playgroud)
我能想到的缺乏功能匹配的唯一可能原因是存在,throw ()但我不知道该怎么做,或者它甚至是一个问题.可能unique_ptr是没有投掷.
否则,无匹配功能正是我期望匹配的功能.
每次声明unique_ptr的实例时,我都不想继续指定析构函数.在这个答案/sf/answers/1163069981/中有一个很好的选择,但我很想知道我的尝试有什么问题.
当然,在现实生活中,它不是int*我想要包装unique_ptr,而是一些不透明(但不是void*)指针.
我的目的是在范围退出时正确释放来自C API的所有指针.
也许我可以将这些指针限制在带有析构函数的类/结构中,但我看不出它会节省多少.
有了@RSahu的提示,我想出了这个,unique_dptr以避免继续指定析构函数,但作为替代std命名空间中的模板删除函数的替代方法: …
我注意到在我的 vxWorks 6 平台上,对write套接字的调用成功完成并返回请求写入的字节数,而且还将 errno 从 0 转换为 19 ( ENODEV)。
我发现这很令人惊讶。
操作成功后可以设置errno吗?
我想用自己的错误代码调用一个完成处理程序,但参数的签名是:
const boost::system::error_code& err
Run Code Online (Sandbox Code Playgroud)
我担心我构造的error_code的生命周期,特别是与异步处理程序,链式处理程序,io_service.post以及对基于堆栈的错误代码的引用的粗略传播有关,这些错误代码已超出范围.
我可以尝试这样的事情:
const boost::system::error_code err =
boost::system::errc::make_error_code(boost::system::errc::bad_message);
handler(&err);
Run Code Online (Sandbox Code Playgroud)
但似乎有点可怕不通过价值; 特别是如果我想使用io_service.post
这样的事情是使用lambdas最好的方式吗?(我也可以在lambda中犯错误)
const boost::system::error_code err =
boost::system::errc::make_error_code(boost::system::errc::bad_message);
io_service.post([error](){ handler(&err); }
Run Code Online (Sandbox Code Playgroud)
这样安全吗?无泄漏?
handler(boost::system::errc::make_error_code(boost::system::errc::bad_message));
Run Code Online (Sandbox Code Playgroud) c++ ×4
boost ×2
boost-asio ×1
constructor ×1
errno ×1
inheritance ×1
pointers ×1
ssl ×1
templates ×1
unique-ptr ×1
vxworks ×1