内存泄漏无法解决 C++
Memory Leak Cant Solve it C++
由于 malloc,我的代码出现了内存泄漏。但是由于指针和结构,我有点困惑。有人能告诉我应该在哪里正确使用我的免费吗?如果我正在寻找的 Programm 是 运行 或不是
,此函数会给我一个布尔值
typedef struct _SYSTEM_PROCESS_INFORMATION_DETAILD
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
LARGE_INTEGER SpareLi2;
LARGE_INTEGER SpareLi3;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
}
SYSTEM_PROCESS_INFORMATION_DETAILD, *PSYSTEM_PROCESS_INFORMATION_DETAILD;
typedef NTSTATUS(WINAPI *PFN_NT_QUERY_SYSTEM_INFORMATION)(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT OPTIONAL PULONG ReturnLength);
BOOLEAN IsProcessRunning(TCHAR* exe_name)
{
size_t bufferSize = 10000;
PSYSTEM_PROCESS_INFORMATION_DETAILD pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)malloc(bufferSize);
ULONG ReturnLength;
PFN_NT_QUERY_SYSTEM_INFORMATION pfnNtQuerySystemInformation = (PFN_NT_QUERY_SYSTEM_INFORMATION)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation");
NTSTATUS status;
TCHAR* name;
while (TRUE)
{
status = pfnNtQuerySystemInformation(SystemProcessInformation, (PVOID)pspid, bufferSize, &ReturnLength);
if (status == STATUS_SUCCESS)
break;
else if (status != STATUS_INFO_LENGTH_MISMATCH)
{
return 1; // error
}
bufferSize *= 2;
pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)realloc((PVOID)pspid, bufferSize);
}
for (;; pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)(pspid->NextEntryOffset + (PBYTE)pspid))
{
name = (pspid->ImageName.Length && pspid->ImageName.Buffer) ? pspid->ImageName.Buffer : L"";
//_tprintf(_T("P-Id: %d, P-Name: %ls\n"), pspid->UniqueProcessId, name);
int result = wcscmp(exe_name, name);
if (result == 0)
{
return TRUE;
}
if (npspid->NextEntryOffset == 0) break;
}
return FALSE;
}
您应该在您的函数中调用 free
,以释放您使用 malloc
分配的内存(并使用 realloc
重新分配)。
问题是你的函数有多个退出点,所以你要注意在每个退出点释放内存。
在 C 语言中,这通常通过 goto
语句解决到一个公共出口点,在那里您可以清理所有资源。
但是,在 C++ 中您可以做得更好。例如,您可以使用 smart 指针,例如 std::unique_ptr
:
auto buffer = std::make_unique< BYTE[] >(bufferSize);
当智能指针实例超出范围时(例如,当函数 returns 时),分配的内存自动 释放。
您可以使用 unique_ptr::get
方法获取指向已分配缓冲区的原始指针。
另一种方法是使用 std::vector<BYTE>
及其 resize
方法。
如果你想获得指向向量缓冲区中第一个元素的指针(元素是连续存储的),你可以使用vector::data
方法。 vector::size
将 return 向量中的项目数。而且,向量中的内存自动释放。
首先,您错误地使用了 Windows API:API 的设计让您可以:
- 第一次使用空缓冲区调用它并检索所需的确切缓冲区大小
- 分配缓冲区
- 再次调用获取信息
像这样:
BOOLEAN IsProcessRunning(TCHAR* exe_name)
{
ULONG bufferSize;
status = pfnNtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &bufferSize);
if (status != STATUS_INFO_LENGTH_MISMATCH)
{
return 1;
}
pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)malloc(bufferSize);
ULONG bufferSize;
status = pfnNtQuerySystemInformation(SystemProcessInformation, (PVOID)pspid, bufferSize, nullptr);
if (status != STATUS_SUCCESS)
{
return 1;
}
for (..)
{
[..]
}
}
接下来,在 for
循环中使用完缓冲区后,您可以简单地使用以下方法释放内存:
free(pspid);
更好的实施
更好的实现方式是使用智能指针。您唯一需要更改的是 pspid
:
的分配
auto pspid = std::make_unique<BYTE[]>(bufferSize);
以及您引用它的方式:pspid.get()
内存会自动释放:)
您可以在每个 'return' 语句之前释放分配的块。
free(pspid);
return ...;
顺便说一句:
return 1; // error
因为你想 return 一个布尔值,你应该 return TRUE 或 FALSE 而不是别的。
由于 malloc,我的代码出现了内存泄漏。但是由于指针和结构,我有点困惑。有人能告诉我应该在哪里正确使用我的免费吗?如果我正在寻找的 Programm 是 运行 或不是
,此函数会给我一个布尔值 typedef struct _SYSTEM_PROCESS_INFORMATION_DETAILD
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
LARGE_INTEGER SpareLi2;
LARGE_INTEGER SpareLi3;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
}
SYSTEM_PROCESS_INFORMATION_DETAILD, *PSYSTEM_PROCESS_INFORMATION_DETAILD;
typedef NTSTATUS(WINAPI *PFN_NT_QUERY_SYSTEM_INFORMATION)(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT OPTIONAL PULONG ReturnLength);
BOOLEAN IsProcessRunning(TCHAR* exe_name)
{
size_t bufferSize = 10000;
PSYSTEM_PROCESS_INFORMATION_DETAILD pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)malloc(bufferSize);
ULONG ReturnLength;
PFN_NT_QUERY_SYSTEM_INFORMATION pfnNtQuerySystemInformation = (PFN_NT_QUERY_SYSTEM_INFORMATION)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation");
NTSTATUS status;
TCHAR* name;
while (TRUE)
{
status = pfnNtQuerySystemInformation(SystemProcessInformation, (PVOID)pspid, bufferSize, &ReturnLength);
if (status == STATUS_SUCCESS)
break;
else if (status != STATUS_INFO_LENGTH_MISMATCH)
{
return 1; // error
}
bufferSize *= 2;
pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)realloc((PVOID)pspid, bufferSize);
}
for (;; pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)(pspid->NextEntryOffset + (PBYTE)pspid))
{
name = (pspid->ImageName.Length && pspid->ImageName.Buffer) ? pspid->ImageName.Buffer : L"";
//_tprintf(_T("P-Id: %d, P-Name: %ls\n"), pspid->UniqueProcessId, name);
int result = wcscmp(exe_name, name);
if (result == 0)
{
return TRUE;
}
if (npspid->NextEntryOffset == 0) break;
}
return FALSE;
}
您应该在您的函数中调用 free
,以释放您使用 malloc
分配的内存(并使用 realloc
重新分配)。
问题是你的函数有多个退出点,所以你要注意在每个退出点释放内存。
在 C 语言中,这通常通过 goto
语句解决到一个公共出口点,在那里您可以清理所有资源。
但是,在 C++ 中您可以做得更好。例如,您可以使用 smart 指针,例如 std::unique_ptr
:
auto buffer = std::make_unique< BYTE[] >(bufferSize);
当智能指针实例超出范围时(例如,当函数 returns 时),分配的内存自动 释放。
您可以使用 unique_ptr::get
方法获取指向已分配缓冲区的原始指针。
另一种方法是使用 std::vector<BYTE>
及其 resize
方法。
如果你想获得指向向量缓冲区中第一个元素的指针(元素是连续存储的),你可以使用vector::data
方法。 vector::size
将 return 向量中的项目数。而且,向量中的内存自动释放。
首先,您错误地使用了 Windows API:API 的设计让您可以:
- 第一次使用空缓冲区调用它并检索所需的确切缓冲区大小
- 分配缓冲区
- 再次调用获取信息
像这样:
BOOLEAN IsProcessRunning(TCHAR* exe_name)
{
ULONG bufferSize;
status = pfnNtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &bufferSize);
if (status != STATUS_INFO_LENGTH_MISMATCH)
{
return 1;
}
pspid = (PSYSTEM_PROCESS_INFORMATION_DETAILD)malloc(bufferSize);
ULONG bufferSize;
status = pfnNtQuerySystemInformation(SystemProcessInformation, (PVOID)pspid, bufferSize, nullptr);
if (status != STATUS_SUCCESS)
{
return 1;
}
for (..)
{
[..]
}
}
接下来,在 for
循环中使用完缓冲区后,您可以简单地使用以下方法释放内存:
free(pspid);
更好的实施
更好的实现方式是使用智能指针。您唯一需要更改的是 pspid
:
auto pspid = std::make_unique<BYTE[]>(bufferSize);
以及您引用它的方式:pspid.get()
内存会自动释放:)
您可以在每个 'return' 语句之前释放分配的块。
free(pspid);
return ...;
顺便说一句:
return 1; // error
因为你想 return 一个布尔值,你应该 return TRUE 或 FALSE 而不是别的。