gpt4 book ai didi

C++ lambda 自传递异常

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:50:31 31 4
gpt4 key购买 nike

当我运行这段代码时,我得到 std::bad_functon_call 异常。我无法弄清楚此异常的原因是什么。它是由 receiveCallback 内部的 async_receive 抛出的。receiveCallback 在调用前是否从内存中清除?

//callback on connection accepted
std::function<void(const boost::system::error_code& error, tcp::socket* socketPtr)> acceptCallback =
[this, onMessageReceivedCallback, acceptCallback](const boost::system::error_code& error, tcp::socket* socketPtr)
{
cout<<"accept: "<<error.message()<<endl;

const int bufferSize = 100;
char* message = new char[bufferSize];

//callback on message received
std::function<void(const boost::system::error_code& error,std::size_t bytes_transferred)> receiveCallback =
[message, bufferSize, socketPtr, onMessageReceivedCallback, receiveCallback](const boost::system::error_code& error,std::size_t bytes_transferred)
{
onMessageReceivedCallback(message, bytes_transferred);

socketPtr->async_receive(
boost::asio::buffer(message, bufferSize),
receiveCallback);
};

socketPtr->async_receive(
boost::asio::buffer(message, bufferSize),
receiveCallback);

//create socket for the next connection
socketPtr = new tcp::socket(io_service_);
//continue accepting connections
acceptor_.async_accept(*socketPtr, std::bind(acceptCallback, std::placeholders::_1, socketPtr));

最佳答案

您的代码是未定义的行为:当 lambda 按值捕获 receiveCallback 时,receiveCallback 尚未初始化,因此 lambda 获取的拷贝是垃圾(使用 GCC 4.7 我什至得到段错误而不是 std::bad_function_call)。顺便说一句,acceptCallback 表现出同样的问题。

一个明显的解决方案是通过引用而不是通过值来捕获receiveCallback,但是这会带来与对象生命周期相关的问题(receiveCallback 对象必须在整个 I/O 操作期间保持事件状态,但一旦您退出 accept lambda,它就会被销毁。

这是先有鸡还是先有蛋的情况:由于生命周期问题,通过引用捕获将不起作用,您需要通过值捕获来解决这个问题,但是通过值捕获会复制未初始化的对象,因此您需要通过引用捕获来解决那。嗯。

请注意,receiveCallback 在另一种方式上是不正确的:您也通过值捕获 message,这意味着无论何时调用 lambda,您都不会得到缓冲区由 boost::asio 填充,但带有 lambda 实例化时创建的缓冲区拷贝(换句话说,又是未初始化的垃圾)。


既然已经进行了诊断,如何修复它并编写工作代码?

在我看来,完全放弃 lambda。编写一个类来保存您的消息 缓冲区和onMessageReceivedCallback,并且具有acceptreceive 成员函数。

根据 boost::asio 的确切 API,您可能需要将您的成员函数“包装”在 std::function 对象中以获得 的回调asio 可以使用 (std::mem_fn 是你的 friend ,不要忘记 std::bind 结果 std 的第一个参数::function 对象到你的类的实例)。

关于C++ lambda 自传递异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16641335/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com