在direct2D中释放渐变笔刷时是否存在潜在内存泄漏? 我有一个简单的C++程序,它简化了272行代码,初始化DistT2D,然后执行一个1000操作循环,在这里只创建ID2D1RealEngestStor集合,然后创建使用ID2D1LooRealthFuntB刷,然后立即释放它们。(释放调用的释放计数降至零,因此表明它们通常应未分配)

在direct2D中释放渐变笔刷时是否存在潜在内存泄漏? 我有一个简单的C++程序,它简化了272行代码,初始化DistT2D,然后执行一个1000操作循环,在这里只创建ID2D1RealEngestStor集合,然后创建使用ID2D1LooRealthFuntB刷,然后立即释放它们。(释放调用的释放计数降至零,因此表明它们通常应未分配),c++,memory-leaks,directx-11,direct2d,C++,Memory Leaks,Directx 11,Direct2d,但是,每次执行此循环后,我都会看到进程保留的内存不断增加,只有在direct2D工厂和设备释放后,才会在最后释放内存,而不是像我预期的那样在每次调用linearGradientBrush->Release()和gradientStopCollection->Release()后释放内存 奇怪的是,当我创建/删除SolidColorBrush而不是LinearGradientBrush(仍在创建/删除gradientStopCollection)时,再也没有观察到内存泄漏 这是不是我做错了,导致g

但是,每次执行此循环后,我都会看到进程保留的内存不断增加,只有在direct2D工厂和设备释放后,才会在最后释放内存,而不是像我预期的那样在每次调用linearGradientBrush->Release()和gradientStopCollection->Release()后释放内存

奇怪的是,当我创建/删除SolidColorBrush而不是LinearGradientBrush(仍在创建/删除gradientStopCollection)时,再也没有观察到内存泄漏

这是不是我做错了,导致gradientStopCollection仍然被分配,因为它仍然被笔刷使用?(但我不明白在这种情况下,调用两个对象上的Release后的引用计数为什么会降为零;而且,如果我添加AddRef或删除Release以触发对象上AddRef/Release的错误计数(并在程序结束时获得非零引用计数的情况)然后,Direct2D调试层指示在调用堆栈上调用kernelbase.dll的d2d1debug3.dll中存在错误,从而表明AddRef/Release计数是正确的;但我仍然通过TaskManager观察到内存泄漏)

任何关于如何解决此问题的帮助都将不胜感激

    #include <windows.h>
    #include <commctrl.h>

    // DirectX header files.
    #include <d2d1_1.h>
    #include <d3d11.h>
    #include <d3d11_1.h>


    bool performAllocUnallocTestLoop(ID2D1DeviceContext* in_deviceContext) {
        ID2D1GradientStopCollection* gradientStopCollection;
        int i;
        ID2D1LinearGradientBrush* linearGradientBrush;
        int cnt;
        ULONG nb;
        D2D1_GRADIENT_STOP gradientStops[2];
        HRESULT hr;
        ID2D1SolidColorBrush* solidColorBrush;

        gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
        gradientStops[0].position = 0.0f;
        gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
        gradientStops[1].position = 1.0f;

        cnt = 1000;
        for (i = 0; i < cnt; i++) {
            hr = in_deviceContext->CreateGradientStopCollection(gradientStops, 2, D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &gradientStopCollection);
            if (!SUCCEEDED(hr)) {
                return false;
            }

            hr = in_deviceContext->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2D1::Point2F(0, 0), D2D1::Point2F(150, 150)), gradientStopCollection, &linearGradientBrush);
            if (!SUCCEEDED(hr)) {
                gradientStopCollection->Release();
                return false;
            }

            /*
                // This code is commented and creates a solidColorBrush instead of a linearGradientBrush.
                // Uncomment this code and comment the creation of the linearGradientBrush above instead and the leak disappears.

            hr = in_deviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow, 1), &solidColorBrush);
            if (!SUCCEEDED(hr)) {
                gradientStopCollection->Release();
                return false;
            }
            */

            nb = linearGradientBrush->Release(); // Comment this line and the linearGradientBrush creation, then uncomment the solidColorBrush creation/release instead
                                 // and the memory leak disappears.
            // nb = solidColorBrush->Release();
            nb = gradientStopCollection->Release();
        }

        return true;
    }

    int main_test_function(ID2D1DeviceContext* in_deviceContext) {
        int i;

        MessageBoxW(NULL, (WCHAR*)L"Before", (WCHAR*)L"Before", MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);

        for (i = 0; i < 10; i++) {
            if (!performAllocUnallocTestLoop(in_deviceContext)) {
                MessageBoxW(NULL, (WCHAR*)L"Some creation failed", (WCHAR*)L"Some creation failed", MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
                return 0;
            }

            if (MessageBoxW(NULL, (WCHAR*)L"After performed another 1000 create/delete of gradientStopCollection+linearGradientBrush (leak observed in TaskManager, resource NOT released)", (WCHAR*)L"After", MB_OKCANCEL | MB_ICONINFORMATION | MB_SETFOREGROUND) == IDCANCEL) {
                break;
            }
        }

        return 0;
    }

    // _____________________________________________________________
    // _ WinMain part: init/dest D3D and D2D factories and devices.
    // _____________________________________________________________

    struct TD2DFactoriesAndDevices {
        ID2D1Factory1* d2dFactory;

        ID3D11Device1* d3dDevice;
        IDXGIDevice* dxgiDevice;
        ID2D1Device* d2dDevice;
        ID2D1DeviceContext* d2dDeviceContext;
    };

    void destFactoriesAndDevices(TD2DFactoriesAndDevices* in_struct) {

        if (in_struct == NULL) {
            return;
        }

        if (in_struct->d3dDevice != NULL) {
            in_struct->d3dDevice->Release();
            in_struct->d3dDevice = NULL;
        }
        if (in_struct->dxgiDevice != NULL) {
            in_struct->dxgiDevice->Release();
            in_struct->dxgiDevice = NULL;
        }
        if (in_struct->d2dDevice != NULL) {
            in_struct->d2dDevice->Release();
            in_struct->d2dDevice = NULL;
        }
        if (in_struct->d2dDeviceContext != NULL) {
            in_struct->d2dDeviceContext->Release();
            in_struct->d2dDeviceContext = NULL;
        }

        if (in_struct->d2dFactory != NULL) {
            in_struct->d2dFactory->Release();
            in_struct->d2dFactory = NULL;
        }

        CoUninitialize();
    }

    bool initFactoriesAndDevices(TD2DFactoriesAndDevices* in_struct,
                                     const wchar_t*& out_error) {
        HRESULT hr;
        D2D1_FACTORY_OPTIONS options;
        ID3D11Device* d3dDevice;
        UINT createDeviceFlags;
        D3D_DRIVER_TYPE driverType;

        if (in_struct == NULL) {
            out_error = L"Can not use NULL pointer";
            return false;
        }

        in_struct->d3dDevice = NULL;
        in_struct->dxgiDevice = NULL;
        in_struct->d2dDevice = NULL;
        in_struct->d2dDeviceContext = NULL;

        in_struct->d2dFactory = NULL;

        // init DCOM
        if (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) != S_OK) {
            out_error = L"Could not init DCOM";
            return false;
        }

        // Create the Direct2D factory.
        ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
    #if defined(_DEBUG)

        options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
        // options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
    #endif

        hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
                                       options, &in_struct->d2dFactory);
        if (!SUCCEEDED(hr)) {
            in_struct->d2dFactory = NULL;
            out_error = L"D2D1CreateFactory failed";
            CoUninitialize();
            return false;
        }

    __create_devices:

        // Create the D3D device on default adapter.
        createDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
        createDeviceFlags |= D3D11_CREATE_DEVICE_SINGLETHREADED;
    #ifdef _DEBUG
        createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
    #endif

        // Creating the d3dDevice
        in_struct->d3dDevice = NULL;

        D3D_FEATURE_LEVEL featureLevels[] =
        {
            D3D_FEATURE_LEVEL_11_1,
            D3D_FEATURE_LEVEL_11_0,
            D3D_FEATURE_LEVEL_10_1,
            D3D_FEATURE_LEVEL_10_0,
            D3D_FEATURE_LEVEL_9_3,
            D3D_FEATURE_LEVEL_9_2,
            D3D_FEATURE_LEVEL_9_1
        };


        hr = D3D11CreateDevice(
            nullptr,
            D3D_DRIVER_TYPE_HARDWARE,
            0,
            createDeviceFlags,
            featureLevels,
            ARRAYSIZE(featureLevels),
            D3D11_SDK_VERSION,
            &d3dDevice,
            nullptr,
            nullptr
            );



        if (FAILED(hr)) {
            in_struct->d3dDevice = NULL;
            goto __create_failed;
        }

        hr = d3dDevice->QueryInterface(__uuidof(ID3D11Device1),
                                              (void**)(&in_struct->d3dDevice));
        if (FAILED(hr)) {
            in_struct->d3dDevice = NULL;
            goto __create_failed;
        }

        d3dDevice->Release();

        // Get a DXGI device interface from the D3D device.
        in_struct->dxgiDevice = NULL;
        hr = in_struct->d3dDevice->QueryInterface(__uuidof(IDXGIDevice),
                                           (void**)(&in_struct->dxgiDevice));
        if (FAILED(hr)) {
            in_struct->dxgiDevice = NULL;
            goto __create_failed;
        }

        // Create a D2D device from the DXGI device.
        hr = in_struct->d2dFactory->CreateDevice(in_struct->dxgiDevice,
                                                         &in_struct->d2dDevice);
        if (FAILED(hr)) {
            in_struct->d2dDevice = NULL;
            goto __create_failed;
        }

        // Create a device context from the D2D device, to create the
                // resources.
        hr = in_struct->d2dDevice->CreateDeviceContext(
                D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &in_struct->d2dDeviceContext);
        if (FAILED(hr)) {
            in_struct->d2dDeviceContext = NULL;
            goto __create_failed;
        }

        // Setting isCreated
    __after_create_devices:

        return true;


    __create_failed:
        destFactoriesAndDevices(in_struct);

        out_error = L"Could not create the devices";
        return false;
    }

    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                             LPSTR lpCmdLine, int nCmdShow) {
        int result;
        const wchar_t* _error;
        TD2DFactoriesAndDevices _struct;

        if (!initFactoriesAndDevices(&_struct, _error)) {
            MessageBoxW(NULL, (WCHAR*)L"An error occured", _error,
                                           MB_OK | MB_ICONINFORMATION);
            return 0;
        }

        result = main_test_function(_struct.d2dDeviceContext);

        destFactoriesAndDevices(&_struct);

        return result;
    }
#包括
#包括
//DirectX头文件。
#包括
#包括
#包括
bool PerformalLocalOctestLoop(设备上下文中的ID2D1DeviceContext*){
ID2D1GradientStopCollection*gradientStopCollection;
int i;
ID2D1LinearGradientBrush*linearGradientBrush;
int-cnt;
乌龙铌;
D2D1_梯度_停止梯度停止[2];
HRESULT-hr;
ID2D1SOLIDCORBRUSH*SOLIDCORBRUSH;
gradientStops[0]。color=D2D1::ColorF(D2D1::ColorF::Yellow,1);
渐变停止[0]。位置=0.0f;
gradientStops[1]。color=D2D1::ColorF(D2D1::ColorF::ForestGreen,1);
渐变停止[1]。位置=1.0f;
cnt=1000;
对于(i=0;i创建gradientStopCollection(gradientStops,2,D2D1\u GAMMA\u 2\u 2,D2D1\u EXTEND\u MODE\u CLAMP和gradientStopCollection);
如果(!成功(hr)){
返回false;
}
hr=in_deviceContext->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2D1::Point2F(0,0)、D2D1::Point2F(150,150))、gradientStopCollection和linearGradientBrush);
如果(!成功(hr)){
gradientStopCollection->Release();
返回false;
}
/*
//此代码将被注释并创建solidColorBrush,而不是linearGradientBrush。
//取消对该代码的注释,并对上面的linearGradientBrush的创建进行注释,则泄漏消失。
hr=in_deviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow,1),&solidColorBrush);
如果(!成功(hr)){
gradientStopCollection->Release();
返回false;
}
*/
nb=linearGradientBrush->Release();//注释此行和linearGradientBrush创建,然后取消对solidColorBrush创建/发布的注释
//内存泄漏消失了。
//nb=solidColorBrush->Release();
nb=梯度停止收集->释放();
}
返回true;
}
int main_test_函数(设备上下文中的ID2D1DeviceContext*){
int i;
MessageBoxW(NULL,(WCHAR*)L“Before”,(WCHAR*)L“Before”,MB_OK | MB|ICONINFORMATION | MB|u SETFOREGROUND);
对于(i=0;i<10;i++){
if(!PerformalLocalOctestLoop(在设备上下文中)){
MessageBoxW(NULL,(WCHAR*)L“某些创建失败”,“WCHAR*)L“某些创建失败”,MB_确定| MB|ICONINFORMATION | MB|u设置前景);
返回0;
}
如果(MessageBoxW(NULL,(WCHAR*)L“在执行gradientStopCollection+linearGradientBrush(在TaskManager中观察到泄漏,资源未释放)”的另一个1000次创建/删除之后),(WCHAR*)L“之后”,MB_OKCANCEL | MB|ICONINFORMATION | MB| MB SETFOREGROUND)=IDCANCEL{
打破
}
}
返回0;
}
// _____________________________________________________________
//_uuWinMain部分:初始/目标D3D和D2D工厂和设备。
// _____________________________________________________________
结构TD2DFacturesAndDevices{
ID2D1Factory1*D2DFFactory;
ID3D11设备1*D3D设备;
idxgDevice*dxgDevice;
ID2D1设备*D2D设备;
ID2D1DeviceContext*d2dDeviceContext;
};
void destFactoriesAndDevices(结构中的TD2DFactoriesAndDevices*){
if(in_struct==NULL){
返回;
}
如果(在结构->d3dDevice!=NULL中){
在_struct->d3dDevice->Release()中;
in_struct->d3dDevice=NULL;
}
如果(在结构->dxgDevice!=NULL中){
在_struct->dxgiDevice->Release()中;
in_struct->dxgiDevice=NULL;
}
如果(在结构->d2dDevice!=NULL中){
在_struct->d2device->Release()中;
in_struct->d2dDevice=NULL;
}
如果(在结构->d2dDeviceContext!=NULL中){
在_struct->d2ddevicontext->Release()中;
在_struct->d2ddevicontext=NULL;
}
如果(在结构->d2dFactory!=NULL中){
在_struct->d2dFactory->Release()中;
in_struct->d2dFactor