在旧的连接池实现中,我发现了这种美丽(经过简化):
#include <memory>
#include <queue>
struct Connection
{
};
auto pool = std::queue<std::shared_ptr<Connection>>{};
auto pushConnection(Connection* connection) -> void
{
// This uses pushConnection as custom deleter in the shared_ptr
pool.emplace(connection, pushConnection);
}
int main()
{
pushConnection(new Connection{});
}
最初的想法是,您可以从池中获取连接,完成后,自定义删除器(pushConnection
)会自动将其返回到池中。
但是,使用相同的自定义删除器将连接存储在池中不仅有点奇怪。
至少会出现资源泄漏:当程序结束时池超出范围时,将调用queue
的析构函数。这将破坏shared_ptr
,这将调用其自定义删除程序,该删除程序会将连接放回到队列中。
我想知道,将emplace
变成目前正在被销毁的queue
也是一种不确定的行为吗?
答案 0 :(得分:0)
正如我所评论的,内存泄漏源于new Connection{}
。
程序UB是吗?我觉得是这样的。
std::queue
使用std::deque
作为默认容器。
The documentation of std::deque::emplace
说:“所有迭代器,包括过去的迭代器,都无效。”
由于std::deque
的析构函数会遍历元素,因此结果必须是UB。