问题描述
所以我得到了一些使用SFML库处理一些简单tcp套接字的代码。因此,在SFML功能的使用下创建了一个套接字,并从一个函数中返回了该套接字作为右值引用。 然后,组织功能将这个套接字传递给(当前仅用于存储),并通知其调用者是否已处理套接字。但是,这无法正常工作。
struct Tcpsocket : public ::sf::Tcpsocket {};
unique_ptr<Tcpsocket>&& TcpListener::nonBlockingNext()
{
unique_ptr<Tcpsocket> new_socket (new Tcpsocket) ;
listener.setBlocking(false);
if( listener.accept(*new_socket) == ::sf::Socket::Status::Done)
{
new_socket->setBlocking(false);
std::cout << "Connection established! " << new_socket.get() << "\n";
return std::move(new_socket);
}
return std::move( unique_ptr<Tcpsocket>(nullptr) );
}
bool ConnectionReception::processNextIncoming()
{
unique_ptr<Tcpsocket> new_socket (listener.nonBlockingNext());
std::cout << " and then " << new_socket.get() << "\n";
if( !new_socket ) return false;
processNewTcpConnection( ::std::move(new_socket) );
return true;
}
先前使用的TcpListener
类在组合中封装了sf :: TcpListener并简单地转发其用法。
TEST(test_NetworkConnection,single_connection)
{
ConnectionReception reception;
reception.listen( 55555 );
std::this_thread::sleep_for( 50ms );
Tcpsocket remote_socket;
remote_socket.connect( "127.0.0.1",55555 );
std::this_thread::sleep_for( 10ms );
EXPECT_TRUE( reception.processNextIncoming() );
}
此测试在我正在编译的两种配置中均以不同的方式失败。
在调试(g++ -g3
中,测试意外失败。
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from test_NetworkConnection
[ RUN ] test_NetworkConnection.single_connection
Connection established! 0x6cf7ff0
and then 0
test\test_NetworkConnection.cpp:24: Failure
Value of: reception.processNextIncoming()
Actual: false
Expected: true
[ Failed ] test_NetworkConnection.single_connection (76 ms)
[----------] 1 test from test_NetworkConnection (78 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (87 ms total)
[ PASSED ] 0 tests.
[ Failed ] 1 test,listed below:
[ Failed ] test_NetworkConnection.single_connection
1 Failed TEST
调试和输出显示,已经到达nonBlockingNext()
的第一个返回,即返回侦听器接受的套接字的返回,但是在随后的processNextIncoming
外部函数中,{ {1}}未设置/ new_socket
是。
在Release中,即与nullptr
一起输出显示承诺,但测试本身因段错误而崩溃,看似在测试拆解中,也许是在释放套接字(我通过进一步的输出确定)时进行了调试,代码不是很成功。
g++ -O3
在-g3编译中进行调试时,我还注意到在'nonBlockingNext()'中[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from test_NetworkConnection
[ RUN ] test_NetworkConnection.single_connection
Connection established! 0xfe7ff0
and then 0xfe7ff0
的构造在返回之前似乎又达到了:
new_socket
最有可能在发布配置中进行了优化的步骤,或者只是gdb变得很奇怪。
出了什么问题?我该如何进行这项工作?我在右值和移动时是否犯了任何错误?
解决方法
您在这里有未定义的行为:
unique_ptr<TcpSocket>&& TcpListener::nonBlockingNext()
{
unique_ptr<TcpSocket> new_socket (new TcpSocket) ;
//...
if( /*...*/)
{
//...
return std::move(new_socket);
}
//...
}
问题是您正在返回对局部变量(new_socket
)的引用。不要因为它是一个右值引用而分心-它仍然是一个引用!您应该改为按值返回unique_ptr
。而且,即使std::move()
返回的值合法,但充其量是没有用的,或者最差的情况是错过了优化-因此,只需将其设为return new_socket
。