gpt4 book ai didi

c++ - HeapFree() 崩溃的可能原因

转载 作者:行者123 更新时间:2023-11-27 22:52:43 29 4
gpt4 key购买 nike

typedef 头文件中:

typedef struct tagMYSTRUCT {
wchar_t mystr[40] = { 0 };
DWORD threadId = NULL;
HANDLE threadHandle = NULL;
HWND receiverWnd = NULL;
} MYSTRUCT, *PMYSTRUCT;

线程创建:

MYSTRUCT ats = *(PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT));

wcscpy(ats.mystr, L"hello");

ats.threadHandle = CreateThread(NULL, 0, MyThread, &ats, 0, &(ats.threadId));

这是使用 HeapFree() 函数的线程。但它崩溃了。我认为这是不好的做法,但我想知道为什么。背后的逻辑是什么以及为什么 HeapFree 会导致程序崩溃?

DWORD WINAPI MyThread(LPVOID lpParam) {

MYSTRUCT ActiveStruct = *(PMYSTRUCT)lpParam;

if (lpParam != NULL) {
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}

...

}

最佳答案

您显然来自另一种语言,它以不同于 C++ 的方式混合了指针和引用的概念。你的用法在 C++ 中是非常不合适的。通过使用非标准函数(HeapAlloc(),它是特定于 Windows 的,而不是 C++ 等)来管理内存,您使事情变得更加复杂。

如果您打算使用 HeapAlloc()(这是非标准的 C++,特定于 Windows)或任何动态分配内存的标准函数,结果需要存储在一个指针中。

MYSTRUCT ats = *(PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT));

wcscpy(ats.mystr, L"hello");

ats.threadHandle = CreateThread(NULL, 0, MyThread, &ats, 0, &(ats.threadId));

它所做的是将 HeapAlloc() 返回的指针转换为指向 MYSTRUCT 的指针,取消引用该指针,该指针将内存位置解释为 的值>MYSTRUCT,并将该值复制到 ats

至少这是一个内存泄漏 - 由 HeapAlloc() 分配的内存丢失了(再也没有使用过,它的地址没有存储在任何地方),而你正在传递 的地址ats 到线程函数。

因此 HeapAlloc() 分配的内存与传递给线程函数的地址之间没有关系。

更糟糕的是线程函数本身,我在这里进行了简化

DWORD WINAPI MyThread(LPVOID lpParam)
{
MYSTRUCT ActiveStruct = *(PMYSTRUCT)lpParam;

if (lpParam != NULL)
{
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}
}

lpParam 将包含创建线程的函数传递的函数中 ats 的地址。

如果创建线程的函数已经返回(毕竟,线程是并行运行的)那么 ats 将不再存在。如果发生这种情况,lpParam 将成为悬空指针(就您的程序而言,不再存在的对象的地址)。

ActiveStruct 现在将成为一个本地对象,它包含传递给函数的地址处的对象拷贝。换句话说,它是 func 先前分配的 ats 的本地拷贝。如果 ats 已不复存在,并且传递的地址悬空,则创建 ActiveStruct 的简单操作会导致未定义的行为。

更糟糕的是,lpParam 是(曾经是)ats 的地址。如果 ats 仍然存在(即创建线程的函数尚未返回),则它不是在堆上创建的,因此不应使用 HeapFree() 释放。如果它不再存在,则也不应将其传递给 HeapFree()。无论哪种方式,都要求 HeapFree() 释放未使用 HeapAlloc() 分配的内存。这几乎肯定会导致运行时错误。

至少,您需要将创建线程的代码更改为

MYSTRUCT *ats = (PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT));    //  note changed position of *

wcscpy(ats->mystr, L"hello"); // note usage of ats as a pointer

DWORD threadID; // we need these since ats is being released by the thread function
HANDLE threadHandle; // it is not a good idea for CreateThread() to use them

threadHandle = CreateThread(NULL, 0, MyThread, ats, 0, &(threadId)); // changes since ats is now a pointer

和线程函数

DWORD WINAPI MyThread(LPVOID lpParam)
{
MYSTRUCT *ActiveStruct = (PMYSTRUCT)lpParam; // this is now a pointer

if (lpParam != NULL)
{
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}
}

由于您对 C++ 内存模型做出了根本错误的假设,我会假设您的代码中的其他内容(您未显示)是错误的。但这应该可以帮助您入门。

关于c++ - HeapFree() 崩溃的可能原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35949231/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com