Windows GUI窗口最小化时崩溃问题排查(附代码)
问题分析与修复方案
你的程序崩溃主要有三个核心问题:
1. limit()函数未实现
代码中多次调用limit()来钳位坐标,但完全没有定义这个函数,这会导致未定义行为(编译报错或运行时崩溃)。必须先实现这个钳位函数,确保坐标落在合法范围内。
2. 重复定义draw_rect函数
代码里出现了两个完全相同的draw_rect函数定义,这会触发编译错误,需要删除其中一个。
3. 窗口最小化时缓冲区内存为NULL
当窗口最小化,GetClientRect返回的客户区宽高为0,此时buffer_memory_size = 0 * 0 * sizeof(unsigned int) = 0,调用VirtualAlloc申请0字节内存会返回NULL。后续绘制函数访问NULL指针直接导致崩溃。需要在绘制前判断宽高是否合法,避免无效绘制。
修复后的完整代码
#include <windows.h> #include <Memoryapi.h> #include <stdio.h> #pragma comment(lib, "Gdi32.lib") #pragma comment(lib, "onecore.lib") //global variables bool run = true; int width, height, buffer_memory_size; void *memory; BITMAPINFO BMINFO; // 实现钳位函数:将value限制在min和max之间 int limit(int min, int max, int value) { if (value < min) return min; if (value > max) return max; return value; } //function used to color background void render_background() { // 宽高为0时直接返回,避免访问NULL if (width <= 0 || height <= 0 || memory == NULL) return; unsigned int *ptr = (unsigned int *)memory; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { *ptr = 0xff5500; ptr++; } } } //function used to draw rectangle void draw_rect(int x0, int y0, int x1, int y1, unsigned int color) { // 宽高为0或内存为空时直接返回 if (width <= 0 || height <= 0 || memory == NULL) return; // 先确保y0 <= y1,避免循环不执行或反向遍历 int y_start = limit(0, height - 1, min(y0, y1)); int y_end = limit(0, height - 1, max(y0, y1)); for (int y = y_start; y <= y_end; y++) { unsigned int *ptr = (unsigned int *)memory + y * width; // 同样确保x0 <= x1 int x_start = limit(0, width - 1, min(x0, x1)); int x_end = limit(0, width - 1, max(x0, x1)); for (int x = x_start; x <= x_end; x++) { ptr[x] = color; } } } LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: run = false; return 0; case WM_SIZE: //obtain the new size of the window and the memory size of new needed buffer RECT R; GetClientRect(hwnd,&R); width = R.right - R.left; height = R.bottom - R.top; buffer_memory_size = width*height*sizeof(unsigned int); //buffer memory size in terms of bytes //allocate memory in the heap for new buffer if (memory != NULL) { VirtualFree(memory,0,MEM_RELEASE); memory = NULL; // 释放后置空,避免野指针 } // 只有宽高都大于0时才申请内存 if (width > 0 && height > 0) { memory = VirtualAlloc(0, buffer_memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); } //update BMINFO with updated class members BMINFO.bmiHeader.biSize = sizeof(BMINFO.bmiHeader); BMINFO.bmiHeader.biWidth = width; BMINFO.bmiHeader.biHeight = height; BMINFO.bmiHeader.biPlanes = 1; BMINFO.bmiHeader.biBitCount = 32; BMINFO.bmiHeader.biCompression = BI_RGB; return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam); } int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //create window class const wchar_t name[] = L"window class"; WNDCLASS wc = {}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = name; wc.lpfnWndProc = MainWndProc; //register window class RegisterClass(&wc); //create window and display window HWND H = CreateWindowExW(0, name, L"First Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 1280, 720, 0, 0, hInstance, 0); HDC hdc = GetDC(H); //game loop while (run) { MSG msg; //input while (PeekMessage(&msg, H, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } //logic render_background(); //drawing rectangle x0 = 400, x1 = 700, y0 = 300, y1 = 500 draw_rect(400,300,700,500,0xff00ff); //rendering:只有宽高合法且内存不为空时才绘制 if (width > 0 && height > 0 && memory != NULL) { StretchDIBits(hdc,0,0,width,height,0,0,width,height,memory,&BMINFO,DIB_RGB_COLORS,SRCCOPY); } } // 程序退出前释放内存 if (memory != NULL) { VirtualFree(memory, 0, MEM_RELEASE); } ReleaseDC(H, hdc); return 0; }
关键修复点说明
- 实现
limit()函数:完成坐标钳位逻辑,确保所有绘制的x/y坐标都落在[0, width-1]和[0, height-1]范围内。 - 删除重复的
draw_rect定义:解决编译错误。 - 空指针与零尺寸判断:在
render_background、draw_rect、StretchDIBits调用前,都先检查width/height是否大于0,以及memory是否为NULL,避免无效内存访问。 - 处理坐标顺序:在
draw_rect中先确保y0 <= y1和x0 <= x1,避免因传入反向坐标导致的异常循环。 - 释放内存后置空指针:避免野指针问题,确保后续判断准确。
- 程序退出时清理资源:释放内存和设备上下文,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Sliferslacker
相关产品推荐
相关产品推荐

