c++ - 将 std::shared_ptr 传递给线程并立即超出范围
问题描述
我正在创建一个小型 C++ 服务器,它应该像这样在无限循环中处理请求。
void Server::start_accept_loop(int server, SSL_CTX* ctx){
sockaddr_in incoming_addr;
socklen_t len = sizeof(incoming_addr);
int client_sock;
SSL* ssl;
while(Server::is_accepting){
client_sock = accept(server, (sockaddr*)&incoming_addr, len);
ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_sock);
if (SSL_accept(ssl) == -1){
printf("Unable to accept ssl connection\n");
}else{
std::shared_ptr<Client> client (new Client(ssl));
std::thread th (background_client, client);
}
}
}
void Server::background_client(std::shared_ptr<Client> client_ptr){
std::shared_ptr<Client> client = client_ptr;
int request = 0;
request = client->get_request();
...
}
我其实有几个问题。
- 当创建的客户端 shared_ptr 在线程创建后超出范围时,它会减少引用计数并释放对象。这是新线程的竞争条件,或者是引用计数在该
std::thread th (background_client, client);
行增加。基本上,我想知道是否需要在 while 循环超出范围并创建新的 shared_ptr 之前等待一段时间,或者引用计数是否立即增加? - 我的第二个问题是关于 SSL 结构指针。如果底层的 client_sock 和 incoming_addr 对象超出范围而没有在堆上动态创建,那么可能依赖于这些的 SSL 连接是否存在问题,或者 SSL 指针是否包含所有这些信息的符合动态副本?
- 还有什么我应该知道的吗?
谢谢你。
解决方案
当创建的客户端 shared_ptr 在线程创建后超出范围时,它会减少引用计数并释放对象。这是新线程的竞争条件,或者是在 std::thread th (background_client, client) 处增加了引用计数;线。基本上,我想知道是否需要在 while 循环超出范围并创建新的 shared_ptr 之前等待一段时间,或者引用计数是否立即增加?
shared_ptr
当超出范围时,引用计数将减少,是的。但是Client
对象不会被销毁,因为它shared_ptr
正在被复制到线程中,立即增加引用计数。线程有一个活动引用,所以在线程结束之前对象不会被销毁。
我的第二个问题是关于 SSL 结构指针。如果底层的 client_sock 和 incoming_addr 对象超出范围而没有在堆上动态创建,那么可能依赖于这些的 SSL 连接是否存在问题,或者 SSL 指针是否包含所有这些信息的符合动态副本?
您没有为 SSL 结构提供sockaddr_in
您创建的 ,因此不必担心超出范围。如果 OpenSSL 需要地址信息,它只会从套接字对象中检索自己的副本。至于你的client_sock
变量,它只是一个整数,它是按值复制的,所以也不用担心超出范围。SSL 结构将拥有它自己的描述符副本,并获得它的所有权,并且描述符所引用的底层套接字对象将不会被释放,直到close()
当 SSL 结构被销毁时,描述符被显式 'd释放SSL_free()
。
还有什么我应该知道的吗?
显示的代码不检查是否accept()
失败。如果 SSL/TLS 握手失败,它会泄漏套接字对象和 SSL 结构。