返回指向结构的指针,如何自动释放内存?
returning pointer to a struct, how can I free memory automatically?
来自WINAPI的return一个大结构"MODULEENTRY32"我想使用一个指针,但需要在函数内部的堆中分配内存而不删除它。然后,当我不想再使用该结构时,我知道我应该使用关键字 delete 来释放内存。
#include <iostream>
#include <cstring>
#include <Windows.h>
#include <TlHelp32.h>
MODULEENTRY32* GetModuleEntry(const char *module_name, int PID)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 *moduleEntry = new MODULEENTRY32; // Remember to delete if don't want leak
moduleEntry->dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, moduleEntry)) {
do {
if (strcmp(moduleEntry->szModule, module_name) == 0) {
return moduleEntry;
}
} while (Module32Next(moduleSnapshot, moduleEntry));
}
CloseHandle(moduleSnapshot);
}
return nullptr;
}
int main()
{
int myRandomPID = 123;
MODULEENTRY32* p = GetModuleEntry("mymodule.dll", myRandomPID);
if (!p) {
std::cout << "Obviously you didn't found your random module of your random PID " << std::endl;
}
delete p; // I just don't want to do this
return 0;
}
如何避免在 main 函数中释放内存? unique_ptr?
编辑:可能的解决方案
#include <iostream>
#include <cstring>
#include <Windows.h>
#include <TlHelp32.h>
bool GetModuleEntry(const char *module_name, int PID, MODULEENTRY32* moduleEntry)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
moduleEntry->dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, moduleEntry)) {
do {
if (strcmp(moduleEntry->szModule, module_name) == 0) {
CloseHandle(moduleSnapshot);
return true;
}
} while (Module32Next(moduleSnapshot, moduleEntry));
}
CloseHandle(moduleSnapshot);
}
return false;
}
int main()
{
int myRandomPID = 123;
MODULEENTRY32 moduleEntry;
if (!GetModuleEntry("mymodule.dll", 123, &moduleEntry)) {
std::cout << "Obviously you didn't find your random module of your random PID " << std::endl;
}
return 0;
}
我建议您不要使用指针,只需 return 完整的 MODULEENTRY32
按值结构。
我也建议你可以把return类型包装成std::pair<bool, MODULEENTRY32>
或类似的类型,这样你可以在必要时记录错误return。
最后,如果找到模块名称,则不会关闭句柄。可以使用一点 RAII 来确保 HANDLE
关闭。
#include <iostream>
#include <cstring>
#include <Windows.h>
#include <TlHelp32.h>
#include <utility>
// Helper struct to automatically close the handle
struct ModuleRAII
{
HANDLE *h;
ModuleRAII(HANDLE* h_) : h(h_){}
~ModuleRAII() { CloseHandle(h); }
};
std::pair<bool, MODULEENTRY32> GetModuleEntry(const char *module_name, int PID)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
// This will close the handle automatically
ModuleRAII raii(&moduleSnapshot);
MODULEENTRY32 moduleEntry = {};
moduleEntry.dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, &moduleEntry)) {
do {
if (strcmp(moduleEntry.szModule, module_name) == 0)
return {true, moduleEntry};
} while (Module32Next(moduleSnapshot, &moduleEntry));
}
}
return {false, MODULEENTRY32()};
}
int main()
{
int myRandomPID = 123;
auto retVal = GetModuleEntry("mymodule.dll", myRandomPID);
MODULEENTRY32& p = retVal.second;
if (!retVal.first) {
std::cout << "Obviously you didn't found your random module of your random PID " << std::endl;
}
return 0;
}
这基本上是该功能的故障安全实现。它尚未经过测试,但显示了使用的各种技术,所有这些都没有动态分配。
注意函数return是std::pair<bool, MODULEENTRY>
,所以基本上参数保持不变。唯一的区别是,对于实际的 MODULEENTRY
.
,您可以通过访问 first
(测试函数是否失败)和 second
来获取信息。
解决方案:
Return 来自 getModuleEntry 函数本身的 unique_ptr。
unique_ptr<MODULEENTRY32> GetModuleEntry(const char *module_name, int PID)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
unique_ptr<MODULEENTRY32> moduleEntry = make_unique<MODULEENTRY32>(); // Remember to delete if don't want leak
moduleEntry->dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, moduleEntry.get())) {
do {
if (strcmp(moduleEntry->szModule, module_name) == 0) {
return moduleEntry;
}
} while (Module32Next(moduleSnapshot, moduleEntry.get());
}
CloseHandle(moduleSnapshot);
}
return nullptr;
}
int main()
{
int myRandomPID = 123;
std::unique_ptr<MODULEENTRY32> s_ptr = GetModuleEntry("mymodule.dll", myRandomPID);
if(s_ptr.get()==nullptr)
{
std::cout << "Obviously you didn't found your random module of your random PID " << std::endl;
}
return 0;
}
来自WINAPI的return一个大结构"MODULEENTRY32"我想使用一个指针,但需要在函数内部的堆中分配内存而不删除它。然后,当我不想再使用该结构时,我知道我应该使用关键字 delete 来释放内存。
#include <iostream>
#include <cstring>
#include <Windows.h>
#include <TlHelp32.h>
MODULEENTRY32* GetModuleEntry(const char *module_name, int PID)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 *moduleEntry = new MODULEENTRY32; // Remember to delete if don't want leak
moduleEntry->dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, moduleEntry)) {
do {
if (strcmp(moduleEntry->szModule, module_name) == 0) {
return moduleEntry;
}
} while (Module32Next(moduleSnapshot, moduleEntry));
}
CloseHandle(moduleSnapshot);
}
return nullptr;
}
int main()
{
int myRandomPID = 123;
MODULEENTRY32* p = GetModuleEntry("mymodule.dll", myRandomPID);
if (!p) {
std::cout << "Obviously you didn't found your random module of your random PID " << std::endl;
}
delete p; // I just don't want to do this
return 0;
}
如何避免在 main 函数中释放内存? unique_ptr?
编辑:可能的解决方案
#include <iostream>
#include <cstring>
#include <Windows.h>
#include <TlHelp32.h>
bool GetModuleEntry(const char *module_name, int PID, MODULEENTRY32* moduleEntry)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
moduleEntry->dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, moduleEntry)) {
do {
if (strcmp(moduleEntry->szModule, module_name) == 0) {
CloseHandle(moduleSnapshot);
return true;
}
} while (Module32Next(moduleSnapshot, moduleEntry));
}
CloseHandle(moduleSnapshot);
}
return false;
}
int main()
{
int myRandomPID = 123;
MODULEENTRY32 moduleEntry;
if (!GetModuleEntry("mymodule.dll", 123, &moduleEntry)) {
std::cout << "Obviously you didn't find your random module of your random PID " << std::endl;
}
return 0;
}
我建议您不要使用指针,只需 return 完整的 MODULEENTRY32
按值结构。
我也建议你可以把return类型包装成std::pair<bool, MODULEENTRY32>
或类似的类型,这样你可以在必要时记录错误return。
最后,如果找到模块名称,则不会关闭句柄。可以使用一点 RAII 来确保 HANDLE
关闭。
#include <iostream>
#include <cstring>
#include <Windows.h>
#include <TlHelp32.h>
#include <utility>
// Helper struct to automatically close the handle
struct ModuleRAII
{
HANDLE *h;
ModuleRAII(HANDLE* h_) : h(h_){}
~ModuleRAII() { CloseHandle(h); }
};
std::pair<bool, MODULEENTRY32> GetModuleEntry(const char *module_name, int PID)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
// This will close the handle automatically
ModuleRAII raii(&moduleSnapshot);
MODULEENTRY32 moduleEntry = {};
moduleEntry.dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, &moduleEntry)) {
do {
if (strcmp(moduleEntry.szModule, module_name) == 0)
return {true, moduleEntry};
} while (Module32Next(moduleSnapshot, &moduleEntry));
}
}
return {false, MODULEENTRY32()};
}
int main()
{
int myRandomPID = 123;
auto retVal = GetModuleEntry("mymodule.dll", myRandomPID);
MODULEENTRY32& p = retVal.second;
if (!retVal.first) {
std::cout << "Obviously you didn't found your random module of your random PID " << std::endl;
}
return 0;
}
这基本上是该功能的故障安全实现。它尚未经过测试,但显示了使用的各种技术,所有这些都没有动态分配。
注意函数return是std::pair<bool, MODULEENTRY>
,所以基本上参数保持不变。唯一的区别是,对于实际的 MODULEENTRY
.
first
(测试函数是否失败)和 second
来获取信息。
解决方案:
Return 来自 getModuleEntry 函数本身的 unique_ptr。
unique_ptr<MODULEENTRY32> GetModuleEntry(const char *module_name, int PID)
{
HANDLE moduleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID);
if (moduleSnapshot != INVALID_HANDLE_VALUE)
{
unique_ptr<MODULEENTRY32> moduleEntry = make_unique<MODULEENTRY32>(); // Remember to delete if don't want leak
moduleEntry->dwSize = sizeof(MODULEENTRY32);
if (Module32First(moduleSnapshot, moduleEntry.get())) {
do {
if (strcmp(moduleEntry->szModule, module_name) == 0) {
return moduleEntry;
}
} while (Module32Next(moduleSnapshot, moduleEntry.get());
}
CloseHandle(moduleSnapshot);
}
return nullptr;
}
int main()
{
int myRandomPID = 123;
std::unique_ptr<MODULEENTRY32> s_ptr = GetModuleEntry("mymodule.dll", myRandomPID);
if(s_ptr.get()==nullptr)
{
std::cout << "Obviously you didn't found your random module of your random PID " << std::endl;
}
return 0;
}