为什么我的程序在使用 HeapAlloc 时崩溃并且正常工作
Why does my program crash when using HeapAlloc and work normally whith malloc
我用C++编写了一个程序,带有以下字符串:
pDataArray[i]->hWritePipes = (HANDLE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HANDLE)*(MAX_THREADS - 1));
当我运行它时,我收到消息:
HEAP[MultyThreading1.exe]: HEAP: Free Heap block 4f5830 modified at 4f5850 after it was freed MultyThreading1.exe has triggered a breakpoint.
我将此字符串替换为
pDataArray[i]->hWritePipes = (HANDLE*)malloc(sizeof(HANDLE)*(MAX_THREADS - 1));
而且该程序似乎运行正常。
你知道第一个版本有什么问题吗?
问候。
所有代码都是下面:
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <iostream>
#include <cstdio>
#include <string.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define MAX_THREADS 3
#define BUF_SIZE 255
#define PIPE_SIZE 64
typedef struct Args
{
char tName[56];
HANDLE hReadPipe;
int n;
HANDLE* hWritePipes/*[MAX_THREADS-1]*/;
int i;
} ARGS, *PARGS;
void ErrorHandler(LPTSTR lpszFunction);
DWORD WINAPI recieverFunction(void *arg);
DWORD WINAPI senderFunction(void *arg);
PARGS initParg(int i);
int _tmain()
{
PARGS pDataArray[MAX_THREADS];
DWORD dwThreadIdArray[MAX_THREADS];
HANDLE hThreadArray[MAX_THREADS];
for (int i = 0; i < MAX_THREADS; i++)
{
pDataArray[i] = initParg(i);
if (i == 0){
pDataArray[i]->hWritePipes = (HANDLE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HANDLE)*(MAX_THREADS - 1));
}
else {
if (!CreatePipe(&pDataArray[i]->hReadPipe, &pDataArray[0]->hWritePipes[i - 1], NULL, NULL)){
ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
}
if (pDataArray[i] == NULL)
ExitProcess(2);
hThreadArray[i] = CreateThread(NULL, 0, i==0 ? senderFunction : recieverFunction, pDataArray[i], 0, &dwThreadIdArray[i]);
if (hThreadArray[i] == NULL)
{
ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
}
WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
for (int i = 0; i<MAX_THREADS; i++)
{
CloseHandle(hThreadArray[i]);
if (pDataArray[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, pDataArray[i]);
pDataArray[i] = NULL; // Ensure address is not reused.
}
}
return 0;
}
PARGS initParg(int i){
PARGS ret = (PARGS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARGS));
ret->i = i;
return ret;
}
DWORD WINAPI senderFunction(void *arg) {
string input;
while (true) {
}
return NULL;
}
DWORD WINAPI recieverFunction(void *arg) {
while (true) {}
return NULL;
}
void ErrorHandler(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code.
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message.
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
// Free error-handling buffer allocations.
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
(发布答案,以免在评论中迷失方向)
正如 Eric 所暗示的,initParg
函数中的HeapAlloc
调用是错误的。您正在为指针(sizeof(PARGS)
)分配足够的空间,但使用结果就像为整个结构分配了足够的空间一样。
PARGS initParg(int i) {
PARGS ret = (PARGS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARGS));
ret->i = i;
return ret;
}
您已分配 4 个字节的内存,但ret->i = i
行写入的偏移量 ~68 字节超过分配块的开头。越界访问正在损坏堆。
此处要采取的纠正措施是分配sizeof(ARGS)
字节。
至于malloc
"修复"问题:
- 您正在使用的
malloc
的实现可能会在内部将分配大小舍入到更大的最小值,以便您的非法写入碰巧不会损坏任何重要内容。 - 您正在使用的
malloc
的实现可能会将空间分配相距足够远,以至于您的非法写入恰好不会损坏任何重要内容。 - 您正在使用的
malloc
的实现可能不会执行与HeapAlloc
正在执行的相同的验证(或者可能仅在free
上执行),因此尽管您的非法写入正在破坏事物,但尚未被注意到。
另请注意,如果切换到 malloc
进行分配,则必须使用 free
进行取消分配。 不能假定HeapFree
兼容。
相关文章:
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 为什么STD ::计数将常数传递给Lambda,而不是在弦上工作时而不是字符
- C++程序已停止工作-求解常微分方程