首页 > 解决方案 > 将 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();
    ...
}

我其实有几个问题。

  1. 当创建的客户端 shared_ptr 在线程创建后超出范围时,它会减少引用计数并释放对象。这是新线程的竞争条件,或者是引用计数在该std::thread th (background_client, client);行增加。基本上,我想知道是否需要在 while 循环超出范围并创建新的 shared_ptr 之前等待一段时间,或者引用计数是否立即增加?
  2. 我的第二个问题是关于 SSL 结构指针。如果底层的 client_sock 和 incoming_addr 对象超出范围而没有在堆上动态创建,那么可能依赖于这些的 SSL 连接是否存在问题,或者 SSL 指针是否包含所有这些信息的符合动态副本?
  3. 还有什么我应该知道的吗?

谢谢你。

标签: c++multithreadingopensslsmart-pointers

解决方案


当创建的客户端 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 结构。


推荐阅读