Search code examples
c++c++11shared-ptrglfw

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


Why does the following code trigger an assert? This code initially worked and at some point started triggering an assert as the shared_ptr fell out of scope.

#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;
}

I've taken just the minimum amount of code that I can to reproduce this, and maybe I misunderstand the use of shared_ptr. I've also tried it with the syntax of:

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

The exact error message I am getting in the output window of the debugger (VS2013) is as follows:

Debug Assertion Failed!

Program: C:\Users\...\xxxx.exe
File: f:\dd\vctools\crt\crtw32\misc\dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

From what I've researched it seems that it is trying to free the shared_ptr twice - is this the case and how can I prevent that? It may be worth mentioning that swapping the type from GLFWwindow to struct test { int i; }; no longer triggers the assert. Does this mean that GLFWwindow is deleting the pointer internally? If so why did the code work at one point but not now?


Solution

  • Most likely because glfwCreateWindow allocates the data using malloc, and std::shared_pointer free the memory using delete. Those are two different memory allocation systems, and should not be mixed.

    Besides, you can't just free the pointer returned by glfwCreateWindow, you need to close the window properly, because you have no idea what other data may have been allocated by glfwCreateWindow. You need a custom delete that calls glfwDestroyWindow.