为什么这个shared_ptr在超出范围时抛出断言

Why is this shared_ptr throwing an assert when it goes out of scope?

本文关键字:范围 断言 shared ptr 为什么      更新时间:2023-10-16

为什么下面的代码会触发断言?这段代码最初起作用,并在shared_ptr超出范围时开始触发断言。

#include <iostream>
#include <memory>
#include "GLFW/glfw3.h"
int main()
{
    if (!glfwInit()){
        std::cout << "Failed to initialize GLFW." << std::endl;
        return -1;
    }
    auto window = std::shared_ptr<GLFWwindow>(glfwCreateWindow(1024, 768, "Test", NULL, NULL));
    return 0;
}

我只使用了尽可能少的代码来复制它,也许我误解了shared_ptr的使用。我也尝试过使用以下语法:

std::shared_ptr<GLFWwindow> window(glfwCreateWindow(1024, 768, "Test", NULL, NULL));

我在调试器(VS2013)的输出窗口中得到的确切错误消息如下:

Debug Assertion Failed!
Program: C:Users...xxxx.exe
File: f:ddvctoolscrtcrtw32miscdbgdel.cpp
Line: 52
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

根据我的研究,它似乎两次试图释放shared_ptr——是这样吗?我该如何防止这种情况?值得一提的是,将类型从GLFWwindow交换到struct test { int i; };不再触发断言。这是否意味着GLFWwindow正在内部删除指针?如果是这样的话,为什么代码在某一时刻起作用,而现在却不起作用?

很可能是因为glfwCreateWindow使用malloc分配数据,而std::shared_pointer使用delete释放内存。这是两种不同的内存分配系统,不应该混合使用。

此外,您不能只释放glfwCreateWindow返回的指针,您需要正确关闭窗口,因为您不知道glfwCreateWindow可能分配了其他哪些数据。您需要一个调用glfwDestroyWindow的自定义删除。

您可以添加这样的自定义析构函数:

auto window = std::shared_ptr<GLFWwindow>(glfwCreateWindow(1024, 768, "Test", NULL, NULL), [](GLFWWindow* window) {
   glfwDestroyWindow(window); 
});