【问题标题】:Static class member throws an exception when constructed静态类成员构造时抛出异常
【发布时间】:2016-07-07 18:38:36
【问题描述】:

我有一个包含另一个类的静态成员的类。

Foo.h
class Foo
{
static DirectXRes dxres;
};
Foo.cpp
DirectXRes Foo::dxres;  // may throw an exception
DirectXRes.h
#include <SDKDDKVer.h>

#ifndef WINVER 
#define WINVER  0x0A00
#endif


#ifndef _WIN32_WINNT
#define _WIN32_WINNT    0x0A00
#endif

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

#include <Windows.h>
#include <Windowsx.h>

#pragma comment (lib, "d2d1.lib")
#pragma comment (lib, "Dwrite.lib")
#pragma comment (lib, "Windowscodecs.lib")
#pragma comment (lib, "Ole32.lib")
#pragma comment (lib, "Shlwapi.lib")
#pragma comment (lib, "Crypt32.lib")
#pragma comment (lib, "d3d11.lib")

#include <d2d1.h>
#include <d2d1_1.h>
#include <d2d1_2.h>
#include <d2d1helper.h>
#include <d2d1_2helper.h>
#include <dwrite.h>
#include <wincodec.h>
#include <d3d11_1.h>

class DirectXRes
{
     DirectXRes()
      : D2DFactory(nullptr),
        WriteFactory(nullptr),
        ImgFactory(nullptr),
        D3DDevice(nullptr),
        ImmediateContext(nullptr),
        D2DDevice(nullptr),
        DXGIAdapter(nullptr),
        D2DContext(nullptr),
        DriverType(D3D_DRIVER_TYPE_NULL),
        FeatureLevel(D3D_FEATURE_LEVEL_11_0)
    {
    }

        ID2D1Factory1* D2DFactory;          // Direct2D factory
        IDWriteFactory* WriteFactory;       // DWrite factory
        IWICImagingFactory* ImgFactory;     // Windows Imaging Component (WIC) factory
        ID3D11Device* D3DDevice;            // Direct3D device
        ID2D1Device* D2DDevice;             // Direct2D device
        ID2D1DeviceContext* D2DContext;     // Direct2D device context
        ID3D11DeviceContext* ImmediateContext;  // Direct3D immediate context
        IDXGIAdapter* DXGIAdapter;              // DXGI adapter
        D3D_FEATURE_LEVEL FeatureLevel;         // Direct3D feature level
        D3D_DRIVER_TYPE DriverType;             // Direct3D driver type
};

我遇到的问题是,如果我在头文件 (DirectXRes.h) 之外实现构造函数,即在 DirectXRes.cpp 中构造静态对象时会出现异常:

Viewer.exe 中 0x7550DAE8 (KernelBase.dll) 处未处理的异常: 0xE0434352(参数:0x80131016、0x00000000、0x00000000、 0x00000000, 0x71F80000)。

如果我将类构造函数的实现保留在头文件中,一切正常。

这个异常有什么解释吗?

【问题讨论】:

  • 你能用静态类成员显示代码吗?你的问题是,我的汽车发动机不工作,这是我右后刹车灯的照片,可能是什么问题?或者,骆驼吃香草冰的声音。它没有什么相关性。
  • @Cheersandhth.-Alf 已添加,但如您所见,我的构造函数只是初始化了一些指针。
  • 另外,如果我将析构函数的实现放在.cpp 文件Unhandled exception at 0x7550DAE8 (KernelBase.dll) in Viewer.exe: 0xC0020001: The string binding is invalid (parameters: 0x8007042B). 中,我会得到一个异常。

标签: c++ exception static directx


【解决方案1】:

我认为这里的问题是静态初始化顺序。对于示例中的静态变量,标准没有指定初始化它们的顺序,因此这可能会有所不同。很可能通过将代码从头文件移动到 cpp 文件,您无意中更改了 Foo::dxres 相对于其他使用它的东西的初始化顺序。在一个版本中,使用它的东西在之后被初始化,而在另一个(崩溃的那个)它之前被初始化,导致它访问未初始化的Foo::dxres,从而导致崩溃。

如果可以更改设计,我将改为通过静态 getter 成员函数访问 Foo::dxres。这样可以保证第一次使用它时可用:

class Foo
{
public:
    static DirectXRes& getDxres();
};

//In either the header or cpp:
DirectXRes& Foo::getDxres()
{
    static DirectXRes dxres;
    return dxres;
}

【讨论】:

  • 那么我在析构函数中遇到的异常呢?可能总是与静态初始化/清理顺序有关吗?
  • 这取决于析构函数中究竟发生了什么,但原则上 - 是的,绝对如此。构造前访问对象是UB,所以一切皆有可能
猜你喜欢
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 2011-03-15
  • 2023-04-01
  • 1970-01-01
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多