You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多次调用GLClear不交换缓冲区致内存泄漏(Windows MSVC)

Windows MSVC环境下OpenGL glClear无缓冲区交换时的内存泄漏问题

在Windows MSVC环境中,调用glClear但不执行缓冲区交换操作时,程序出现内存泄漏。无法确定这是显卡驱动问题还是代码实现错误,恳请帮忙测试该问题,或提供相关排查思路。


代码概述(完整代码见下文)

static bool CloseFlag = false;

LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ 
    static PAINTSTRUCT ps;

    switch(uMsg) 
    {
        case WM_SIZE:
            glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
            PostMessage(hWnd, WM_PAINT, 0, 0);
            return 0;

        case WM_CHAR:
            //Handle input....
            return 0;

        case WM_CLOSE:
            CloseFlag = true;
            return 0;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam); 
} 

HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height, 
           BYTE type, DWORD flags)
{
    //Create window (with double buffer) and register it...
}    

int main ()
{
    hWnd = CreateOpenGLWindow("minimal", 0, 0, 256, 256, PFD_TYPE_RGBA, 0);

    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);

    gladLoadWGL(hDC);
    gladLoadGL();
    ShowWindow(hWnd, SW_SHOW);

    while(!CloseFlag)
    {
        //Handles input
        while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        glClear(GL_COLOR_BUFFER_BIT);
    }

    wglMakeCurrent(NULL, NULL);
    ReleaseDC(hWnd, hDC);
    wglDeleteContext(hRC);
    DestroyWindow(hWnd);

    return 0;
}

可复现问题的最简Win32代码

#ifndef UNICODE
#define UNICODE
#define _UNICODE
#endif

#include <windows.h>            /* must include this before GL/gl.h */
#include "glad/glad.h"
#include "glad/glad_wgl.h"
#include "wglext.h"
#include <string>

static bool CloseFlag = false;

void display(HDC hDC)
{
    /* rotate a triangle around */
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_TRIANGLES);
    glColor3f(1.0f, 0.0f, 0.0f);
    glVertex2i(0,  1);
    glColor3f(0.0f, 1.0f, 0.0f);
    glVertex2i(-1, -1);
    glColor3f(0.0f, 0.0f, 1.0f);
    glVertex2i(1, -1);
    glEnd();
    glFlush();

    SwapBuffers(hDC);
}

void JustClear()
{
    glClear(GL_COLOR_BUFFER_BIT);
}


LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ 
    static PAINTSTRUCT ps;

    switch(uMsg) 
    {
        case WM_SIZE:
            glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
            PostMessage(hWnd, WM_PAINT, 0, 0);
            return 0;

        case WM_CHAR:
            switch (wParam) 
            {
                case 27:            /* ESC key */
                    //PostQuitMessage(0);
                    CloseFlag = true;
                    break;
            }
            return 0;

        case WM_CLOSE:
            CloseFlag = true;
            //PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam); 
} 

HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height, 
           BYTE type, DWORD flags)
{
    int         pf;
    HDC         hDC;
    HWND        hWnd;
    WNDCLASS    wc;
    PIXELFORMATDESCRIPTOR pfd;
    static HINSTANCE hInstance = 0;

    /* only register the window class once - use hInstance as a flag. */
    if (!hInstance) {
        hInstance = GetModuleHandle(NULL);
        wc.style         = CS_OWNDC;
        wc.lpfnWndProc   = (WNDPROC)WindowProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hInstance;
        wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = NULL;
        wc.lpszMenuName  = NULL;
        wc.lpszClassName = L"OpenGL";

        if (!RegisterClass(&wc)) {

            return NULL;
        }
    }

    std::wstring className = L"OpenGL";

    hWnd = CreateWindow(className.c_str(), className.c_str(), WS_OVERLAPPEDWINDOW |
            WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
            x, y, width, height, NULL, NULL, hInstance, NULL);

    if (hWnd == NULL) {
        return NULL;
    }

    hDC = GetDC(hWnd);

    /* there is no guarantee that the contents of the stack that become
       the pfd are zeroed, therefore _make sure_ to clear these bits. */
    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize        = sizeof(pfd);
    pfd.nVersion     = 1;
    pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | flags;
    pfd.iPixelType   = type;
    pfd.cColorBits   = 32;

    pf = ChoosePixelFormat(hDC, &pfd);
    if (pf == 0) {
        return 0;
    } 
 
    if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
        return 0;
    } 

    DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

    ReleaseDC(hWnd, hDC);

    return hWnd;
}    

int main ()
{
    HDC hDC;                /* device context */
    HGLRC hRC;              /* opengl context */
    HWND  hWnd;             /* window */
    MSG   msg;              /* message */



    hWnd = CreateOpenGLWindow("minimal", 0, 0, 256, 256, PFD_TYPE_RGBA, 0);
    if (hWnd == NULL)
        exit(1);

    hDC = GetDC(hWnd);
    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);

    if(!gladLoadWGL(hDC))
    {
        return -1;
    }

    if (!gladLoadGL())                  //Load Glad
    {
        return -1;
    }

    ShowWindow(hWnd, SW_SHOW);

    while(!CloseFlag)
    {
        //Handles input
        while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        //Render
        //display(hDC);
        JustClear();
    }

    wglMakeCurrent(NULL, NULL);
    ReleaseDC(hWnd, hDC);
    wglDeleteContext(hRC);
    DestroyWindow(hWnd);

    return 0;
}

注:wglext.h取自Khronos OpenGL注册表


OpenGL Glad配置信息

/*

    OpenGL loader generated by glad 0.1.36 on Fri Oct 28 11:12:34 2022.

    Language/Generator: C/C++
    Specification: gl
    APIs: gl=3.3
    Profile: compatibility
    Extensions:
        
    Loader: True
    Local files: False
    Omit khrplatform: False
    Reproducible: False

    Commandline:
        --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions=""
*/

同时使用了包含所有扩展的Glad wgl 1.0版本。


使用的CMake配置

cmake_minimum_required(VERSION 3.14)

set (CMAKE_CXX_STANDARD 11)

# For Clang to do parsing
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set the project name
project(Example)


add_executable(EXAMPLE_EXE ${CMAKE_CURRENT_LIST_DIR}/Src/main.cpp)


add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/External/glad_v0.1.36")

find_package(OpenGL REQUIRED)

target_include_directories(EXAMPLE_EXE PUBLIC "${CMAKE_CURRENT_LIST_DIR}/External/wglExt")

target_link_libraries(EXAMPLE_EXE PUBLIC OpenGL::GL glad)

内容的提问来源于stack exchange,提问作者Eds

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:15:38