Closed awen162 closed 2 years ago
看样子是发生了越界读,原因是客户端发送的字符串少发了'\0'。已经修复,可以参考这个提交。 https://github.com/netcan/asyncio/commit/1481361b11846a9a495a1f67e1b513eca9df02df#diff-4a4b47f02ae41b2a8b7e9512e447950c24862dfe67049798ff0653c047e210caR15
谢谢答复! 有个疑问:没有修改echo_client代码前,测试没有问题。那里也是没有添加结束符的。现在就改调用wait_for就有问题了,这里面有没有可能还有其它问题? 麻烦帮忙分析下,或者有什么方法进行分析,我可以尝试去分析下,谢谢!
另外发现个问题: auto data = co_await stream.read(100); 中,data.data()的地址,与stream.read中分配的result.data()地址一致。说明是使用了移动构造。 auto data = co_await asyncio::wait_for(stream.read(100), 300ms);中,data.data()的地址,与stream.read中分配的result.data()地址不是一致。说明是使用了拷贝或者赋值构造,这里是否可以优化下?
另外发现个问题: auto data = co_await stream.read(100); 中,data.data()的地址,与stream.read中分配的result.data()地址一致。说明是使用了移动构造。 auto data = co_await asyncio::wait_for(stream.read(100), 300ms);中,data.data()的地址,与stream.read中分配的result.data()地址不是一致。说明是使用了拷贝或者赋值构造,这里是否可以优化下?
你分析的对,中间应该是发生了拷贝构造。可以优化,得找出发生拷贝构造的时机点,然后通过完美转发之类的移动。暂时没时间改,你可以尝试提下PR,或者等我后续修复也行。
两种情况对比测试发现,在result.h头文件中,调用如下的左值和右值函数,导致一个使用移动构造,一个使用赋值构造。 具体要如何修复,我也不是很清楚。
wait_for 调用了第一个函数进行结果赋值,将return res,修改为return std::move(res)测试可以,但是不清楚会不会带来其它问题。 非wait_for 调用了第二个函数进行结果赋值
constexpr T result() & {
if (auto exception = std::get_if<std::exception_ptr>(&result_)) {
std::rethrow_exception(*exception);
}
if (auto res = std::get_if<T>(&result_)) {
return *res;
}
throw NoResultError{};
}
constexpr T result() && {
if (auto exception = std::get_if<std::exception_ptr>(&result_)) {
std::rethrow_exception(*exception);
}
if (auto res = std::get_if<T>(&result_)) {
return std::move(*res);
}
throw NoResultError{};
}
两种情况对比测试发现,在result.h头文件中,调用如下的左值和右值函数,导致一个使用移动构造,一个使用赋值构造。 具体要如何修复,我也不是很清楚。
wait_for 调用了第一个函数进行结果赋值,将return res,修改为return std::move(res)测试可以,但是不清楚会不会带来其它问题。 非wait_for 调用了第二个函数进行结果赋值
constexpr T result() & { if (auto exception = std::get_if<std::exception_ptr>(&result_)) { std::rethrow_exception(*exception); } if (auto res = std::get_if<T>(&result_)) { return *res; } throw NoResultError{}; } constexpr T result() && { if (auto exception = std::get_if<std::exception_ptr>(&result_)) { std::rethrow_exception(*exception); } if (auto res = std::get_if<T>(&result_)) { return std::move(*res); } throw NoResultError{}; }
那应该就是这一行的问题了: https://github.com/netcan/asyncio/blob/master/include/asyncio/wait_for.h#L21
改成:
return std::move(result_).result();
然后所有测试通过的话,应该就没问题了。
两种情况对比测试发现,在result.h头文件中,调用如下的左值和右值函数,导致一个使用移动构造,一个使用赋值构造。 具体要如何修复,我也不是很清楚。 wait_for 调用了第一个函数进行结果赋值,将return res,修改为return std::move(res)测试可以,但是不清楚会不会带来其它问题。 非wait_for 调用了第二个函数进行结果赋值
constexpr T result() & { if (auto exception = std::get_if<std::exception_ptr>(&result_)) { std::rethrow_exception(*exception); } if (auto res = std::get_if<T>(&result_)) { return *res; } throw NoResultError{}; } constexpr T result() && { if (auto exception = std::get_if<std::exception_ptr>(&result_)) { std::rethrow_exception(*exception); } if (auto res = std::get_if<T>(&result_)) { return std::move(*res); } throw NoResultError{}; }
那应该就是这一行的问题了: https://github.com/netcan/asyncio/blob/master/include/asyncio/wait_for.h#L21
改成:
return std::move(result_).result();
然后所有测试通过的话,应该就没问题了。
按照你给的修改方案,58个测试用例测试都可以了。wait_for那里也没有再使用赋值构造了,直接使用了移动构造。
在测试echo_client时,使用wait_for为read增加超时机制。在很快收到echo_server响应后,打印data.data()数据时,程序coredump了。请帮忙看看是什么问题,谢谢!
运行环境: Ubuntu 18.04.4 LTS gcc version 11.1.0
测试代码如下:
输出和报错信息如下: