Removed post
How to fix this smart pointer crash on exit?
The code below is a minimal version of the actual code of the project, it's just a skeleton, but I cannot reproduce the same problem, I cannot reproduce the same crash because this simplified code doesn't crash. What could be the possible reason of the crash on exit? Can anyone helps me how to fix that crash?
I posted a thread before this then it was automatically deleted, maybe because I shared an idea from a famous chat bot, you know what's its name. Is it allowed to show an idea from such thing? Or maybe my thread was deleted because I edited it just after I posted due to typo? I don't know.
When exit after main(), the crash message is:
Debug Assertion Failed! File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp Expression: _CrtIsValidHeapPointer(block)
Crash on exit after main():
class SceneNode_d; typedef shared_ptr<SceneNode_d> SceneNode;
class Scene_d; typedef shared_ptr<Scene_d> Scene;
enum SceneNodeType {
SceneNodeType_None,
SceneNodeType_Light,
SceneNodeType_Mesh,
SceneNodeType_Scene,
};
class SceneNode_d : public std::enable_shared_from_this<SceneNode_d> {
private:
SceneNode _sharedThis = nullptr;
public:
SceneNode_d(SceneNodeType type) {
}
virtual ~SceneNode_d() {
};
void initSharedThis() {
// This function cannot be called in the constructor because according to ChatGPT: When using std::enable_shared_from_this to manage the lifetime of an object, it is important to create a std::shared_ptr to the object before calling the constructor.
_sharedThis = shared_from_this();
}
};
class Scene_d : public SceneNode_d {
public:
Scene_d() : SceneNode_d(SceneNodeType_Scene) {
}
~Scene_d() {
};
};
class Data_d {
private:
std::vector<Scene> _scenes = {};
public:
static shared_ptr<Data_d> getData() {
// Idea from ChatGPT, check "2023-01-19 - Smart pointer crash on exit.docx".
static shared_ptr<Data_d> instance = make_shared<Data_d>();
return instance;
// Old wrong method, a global variable: g_data: If it's a shared_ptr then it's impossible to write "Data g_data = nullptr;" in "data.cpp" otherwise it will become 0xcccccccccccccccc.
// https://stackoverflow.com/questions/34534927/using-smart-pointers-as-global-variables
// https://www.reddit.com/r/cpp_questions/comments/5p7ltq/about_smart_pointers_for_global_object/
}
Scene addScene();
};
Scene Data_d::addScene() {
auto data = Data_d::getData();
Scene scene = make_shared<Scene_d>();
scene->initSharedThis();
data->_scenes.push_back(scene);
return scene;
}
class Window_d {
public:
std::weak_ptr<Scene_d> _wptr_backgrondScene = {};
void enableBackgroundScene(bool isPrimaryContext) {
auto data = Data_d::getData();
auto ptr = lock_weak_ptr(_wptr_backgrondScene);
if (!ptr) {
_wptr_backgrondScene = data->addScene();
}
// ...
}
};
typedef shared_ptr<Window_d> Window;
int main() {
Window wnd = make_shared<Window_d>();
wnd->enableBackgroundScene(true);
return 0;
} // <-- The crash in the real project happens here.
Developer technologies C++
5 answers
Sort by: Most helpful
-
-
Manda Rajo 141 Reputation points
2023-01-22T10:42:20.6733333+00:00 I forgot to mention that if I comment or remove
scene->initSharedThis();
which usesshared_from_this()
then there is no crash on exit. But when I use it then there is a crash, but that line must be used, but the real cause of the problem is unknown. -
RLWA32 49,536 Reputation points
2023-01-22T10:42:34.39+00:00 The comments in the UCRT source code regarding this assertion are --
// If this assertion fails, a bad pointer has been passed in. It may be // totally bogus, or it may have been allocated from another heap. The // pointer must have been allocated from the CRT heap.
So you need to do some debugging to find where the pointer has been corrupted.
You can use the facilities of the CRT Debug Heap to help find the problem. One way is to check heap integrity during allocation/deallocation. This checking will slow execution of debug builds, but corruption problems will be identified much quicker.
-
-
Manda Rajo 141 Reputation points
2023-01-23T15:34:12.1533333+00:00 Code on top of the common header file:
// ChatGPT: Include <crtdbg.h> before including any other headers. #ifndef NDEBUG #define DEBUG_CRT #endif #ifdef DEBUG_CRT #define _DEBUG #define _CRTDBG_MAP_ALLOC // ChatGPT: Used to enable the mapping of the memory allocation to the file and line number where the allocation occurs. However, you need to enable this mapping before any memory allocation occurs in your program. #include <crtdbg.h> // _CrtSetDbgFlag(), malloc(), realloc(), free(), ... #include <memory> // std::shared_ptr, std::weak_ptr, ... #else // Need: malloc(), realloc(), free(), ... #include <memory> // std::shared_ptr, std::weak_ptr, ... #endif using std::shared_ptr; using std::unique_ptr; using std::weak_ptr; using std::make_shared;
More infomation on Data_d, both the Method 1 and the Method 2 have the same crash on exit.
class Data_d { friend class Scene_d; typedef shared_ptr<Scene_d> Scene; private: std::vector<Scene> _scenes = {}; public: #if 0 // Method 1: Idea from ChatGPT. static shared_ptr<Data_d> getData() { // Idea from ChatGPT static shared_ptr<Data_d> instance = make_shared<Data_d>(); return instance; } #else // Method 2: Idea from ChatGPT. Maybe not thread-safe. static Data_d *getData() { static Data_d *instance = new Data_d(); return instance; } static void destroy() { auto data = getData(); delete data; } #endif Scene addScene(AppBase_d *appBase); private: Light addLight_sun(const glm::vec3 &location, const glm::vec3 &rotation, float strength); };
A cause of the crash but I don't know how to fix
If I comment that line
data->_scenes.push_back(scene);
below then there is no crash, but if it's evaluated uncommented then there is the crash. Note that I use only the member variable_scenes
there on that line, which means it's not used anywhere else but there's still the crash, why? So I realize maybe it's because ofData_d
orscene
but how to fix it?Scene Data_d::addScene(AppBase_d *appBase) { auto data = Data_d::getData(); Scene scene = make_shared<Scene_d>(appBase); data->_scenes.push_back(scene); // <-- This causes the crash on exit. return scene; } void Window_d::enableBackgroundScene(bool isPrimaryContext) { auto data = Data_d::getData(); auto ptr = lock_weak_ptr(_wptr_backgrondScene); if (!ptr) { _wptr_backgrondScene = data->addScene(this->_appBase); // <-- The problem is this. } if (isPrimaryContext) { _appBase->setPrimaryContext(_ctx); } }
How to find the exact location of the memory problem?
In a .cpp file, why the error in a message box doesn't show?
#ifdef DEBUG_CRT int reportHook(int reportType, char *userMessage, int *retVal) { // Idea from ChatGPT if (reportType == _CRT_ASSERT) { // Print detailed error message //_CrtDbgReport(_CRT_ASSERT, NULL, 0, NULL, "%s", userMessage); [wrong] It's a recursive function that causes an infinite loop. EMC_ERROR(userMessage); // <-- This should show a message box, but it doesn't show because 'reportHook' is not called. return TRUE; } return FALSE; } #endif void AppBase_d::init(const char *projectName, int renderingApi) { #ifdef DEBUG_CRT // Check for heap integrity and memory leaks { // https://learn.microsoft.com/en-us/visualstudio/debugger/crt-debug-heap-details?view=vs-2022#BKMK_Check_for_heap_integrity_and_memory_leaks int flag = _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF; #if 1 flag |= _CRTDBG_CHECK_ALWAYS_DF; // Causes _CrtCheckMemory to be called at every allocation and deallocation. This slows execution, but catches errors quickly. #endif _CrtSetDbgFlag(flag); // Problem: Why the callback 'reportHook' is never called? _CrtSetReportHook(&reportHook); // Doesn't work, the meessage box is not shown, why? //_CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, &reportHook); // Doesn't work, the meessage box is not shown, why? } #endif }
In main.cpp:
int main() { App app = make_shared<App_d>(); app->init(_PROJECT_NAME, RENDERINGAPI); Window window1 = app->createWindow("Window1", {1280, 720}); window1->enableBackgroundScene(true); int r = app->main(); app.reset(); #ifdef DEBUG_CRT _CrtDumpMemoryLeaks(); // Note: This prints memory leaks for example, but in VSCode you must launch with the [bug icon] instead of the [>] icon to make it appears. #endif return 0; }
In VSCode, this is what's printed in the DEBUG CONSOLE tab on exit when
data->_scenes.push_back(scene);
is uncommented:HEAP[emc-editor_opengl_debug.exe]: Invalid address specified to RtlValidateHeap( 0000028DB29D0000, 0000028DB29E3370 )
But that message doesn't tell me the exact location of the problem, please help.