2016-07-07 2 views
2

У меня есть класс, который содержит статический член другого класса.Статический член класса генерирует исключение при построении

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 Я получаю исключение, когда статический объект построен:

Необработанное исключение в 0x7550DAE8 (KernelBase.dll) в Viewer.exe: 0xE0434352 (параметры: 0x80131016, 0x00000000, 0x00000000, 0x00000000 , 0x71F80000).

Хотя, если я сохраняю реализацию конструктора классов в файле заголовка, все работает отлично.

Есть ли объяснения для этого исключения?

+1

Не могли бы вы показать код ** со статическим членом класса **? Вопрос в том, что мой автомобильный двигатель не работает, вот фотография моего правого заднего тормоза, что может быть неправильным? Или звук верблюда, извергающего ванильный лед. Это мало актуально. –

+0

@ Cheersandhth.-Alf Добавлено, но, как вы можете видеть, мой конструктор просто инициализирует некоторые указатели. – Nick

+0

Кроме того, я получаю исключение, если я помещаю реализацию destructor в файл .cpp 'Необработанное исключение в 0x7550DAE8 (KernelBase.dll) в Viewer.exe: 0xC0020001: привязка строки недействительна (параметры: 0x8007042B) .'. – Nick

ответ

2

Я думаю, что проблема здесь - это статический порядок инициализации. Со статическими переменными, такими как один в вашем примере, стандарт не указывает порядок, в котором они должны быть инициализированы, поэтому это может различаться. Скорее всего, перемещая код из файла заголовка в файл cpp, вы непреднамеренно меняете порядок инициализации Foo::dxres относительно того, что его использует. В одной версии, то, что ее использует, инициализируется после, а в другой (тот, который выходит из строя) он инициализируется до этого, заставляя его получить доступ к неинициализированному Foo::dxres, который вызывает сбой.

Если можно изменить дизайн, я бы сделал Foo::dxres доступным через функцию статического члена-приемника. Таким образом, будет гарантировано быть доступным в первый раз, когда захочется его использовать:

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

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

А как насчет исключения, которое я получаю в деструкторе? Может ли это быть всегда связано со статическим порядком инициализации/очистки? – Nick

+0

Это зависит от того, что именно происходит в деструкторе, но в принципе - да, абсолютно. Доступ к объекту перед строительством - UB, поэтому все возможно – Smeeheey

Смежные вопросы