Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

13.12.2009, 11:55

zugriffsverletzung bei singleton klasse

Guten Morgen meine Freunde,

ich habe ein kleines Problem, ich habe diese (noch nicht fertige) klasse:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class NE_EXPORT CDirect3D : public CEngine
{
    private:

        CDirect3D(){}
        static CDirect3D* instance;

        LPDIRECT3D9 direct3d;
        LPDIRECT3DDEVICE9 d3ddevice;
        D3DPRESENT_PARAMETERS d3dpp;

    public:

        static CDirect3D* Instance();
        neResult Create(sConfig* config, HWND hWnd);
};


dazu gehört jetzt diese cpp datei:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "neCDirect3D.h"

CDirect3D* CDirect3D::Instance()
{
    if(instance == NULL) instance = new CDirect3D();
    return instance;
}

neResult CDirect3D::Create(sConfig* config, HWND hWnd)
{
    HRESULT r;

    direct3d = Direct3DCreate9(D3D_SDK_VERSION);
    if(direct3d == NULL)
    {
        EngineLog.WriteBadPointer("d3d");
        return NE_D3DERROR;
    }

    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
    d3dpp.BackBufferWidth               = config->d3d.d3dpm.Width;
    d3dpp.BackBufferHeight              = config->d3d.d3dpm.Height;
    d3dpp.BackBufferFormat              = config->d3d.d3dpm.Format;
    d3dpp.BackBufferCount               = 1;
    d3dpp.MultiSampleType               = config->d3d.mstype;
    d3dpp.MultiSampleQuality            = config->d3d.msquality;
    d3dpp.SwapEffect                    = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow                 = hWnd;
    d3dpp.Windowed                      = config->d3d.windowmode;
    d3dpp.EnableAutoDepthStencil        = false;
    d3dpp.AutoDepthStencilFormat        = config->d3d.zstencilformat;
    d3dpp.Flags                         = 0;
    d3dpp.FullScreen_RefreshRateInHz    = config->d3d.d3dpm.RefreshRate;
    d3dpp.PresentationInterval          = D3DPRESENT_INTERVAL_DEFAULT;


    r = direct3d->CreateDevice(config->d3d.adapter, config->d3d.devicetype, hWnd, 0, &d3dpp, &d3ddevice);
    if(FAILED(r)) EngineLog.WriteStringToLog("D3DDevice could not be created", NELOG_ERROR);
    return NE_OK;
}



CDirect3D* CDirect3D::instance = NULL;



aus irgendeinem mir gerade nicht verständlichen Grund kann ich bei den Definition der Create Methode nicht auf die Membervariablen der Klasse zugreifen.
Diese Zeile:

C-/C++-Quelltext

1
direct3d = Direct3DCreate9(D3D_SDK_VERSION);

bewirkt, dass ich beim ausführen des Programms die Meldung bekomme, dass an der Stelle 0x00000004 nicht geschrieben werden kann.
Ich stehe gerade irgendwie auf dem Schlauch kann das?

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

2

13.12.2009, 12:16

Wurde CDirect3D::Instance() auch aufgerufen ?

Edit: Blöde Frage... muss ja...

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

3

13.12.2009, 13:01

Ich vermute, dass es daran liegt, dass die Initialisierung von statischen Variablen über Quelldatein undefiniert ist. Sprich, wenn du Instance aufrufst, ist die Member instance noch nicht auf 0 gesetzt und daher wird da kein Speicher angefordert und du kriest einen 0 Zeiger zurück und dann kriegst du einen solchen Fehler.

Google doch mal nach Meyers Singleton. Das ist fast, wie das deinig, ausser, dass du das hier machst:

C-/C++-Quelltext

1
2
3
4
5
CDirect3D* CDirect3D::Instance()
{
    static CDirect3D instance;
    return &instance;
} 

So hast du garantiert einen gültigen Zeiger und du kannst die Datenmember wegschmeissen.

the[V]oid

Alter Hase

Beiträge: 775

Wohnort: Aachen

  • Private Nachricht senden

4

13.12.2009, 13:05

Zitat von »"drakon"«

Ich vermute, dass es daran liegt, dass die Initialisierung von statischen Variablen über Quelldatein undefiniert ist.


Ist das so?! Hab ich noch nie gehört. Und wie soll man statische Variablen sonst initialisieren? Also ich meine, mich zu erinnern, dass es bei uns damals im Info-Praktikum 2 auch so gemacht wurde.
<< an dieser Stelle ist eine Signatur verstorben >>

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

13.12.2009, 13:07

Zitat von »"the[V«

oid"]

Zitat von »"drakon"«

Ich vermute, dass es daran liegt, dass die Initialisierung von statischen Variablen über Quelldatein undefiniert ist.


Ist das so?! Hab ich noch nie gehört. Und wie soll man statische Variablen sonst initialisieren? Also ich meine, mich zu erinnern, dass es bei uns damals im Info-Praktikum 2 auch so gemacht wurde.


Er meint die Reihenfolge in der die initialisiert werden. Das wird zum Problem wenn er z.B. im Ctor einer globalen Variable auf diesen Singleton zugreift.

Allerdings lässt die Fehlermeldung oben drauf schließen dass aus irgendeinen Grund die Create() Methode auf einem Nullzeiger aufgerufen wird...
Von da her wärs jetzt mal interessant zu sehen wie und wo genau die Create Methode aufgerufen wird.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

6

13.12.2009, 13:15

Ja. Ich meinte die Reihenfolge.

Das gezeigete muss den Fehler nicht erzeugen, kann es aber, im richtigen, respektive falschem Kontext.

Anyway würde ich ihm zu der anderen Variante raten.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

13.12.2009, 13:18

Zitat von »"drakon"«

Anyway würde ich ihm zu der anderen Variante raten.


Wenn, dann so jap. Wobei das Meyers Singleton eigentlich gleich ne Referenz zurückgeben kann statt nem Zeiger ;)

Ich würde aber generell dazu raten kein Singleton zu verwenden :p

8

13.12.2009, 13:19

ich hab das mal ausgetauscht und so geändert:

C-/C++-Quelltext

1
2
3
4
5
CDirect3D* CDirect3D::Instance()
{
    static CDirect3D instance;
    return &instance;
}

bekomme aber immernoch den selben fehler.

der context sieht so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "NeverEndingEngine/NeverEndingEngine.h"

int WINAPI WinMain( HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR CmdLine,
                    int nCmdShow)
{

    CEngine* Engine = CEngine::Instance();
    CDirect3D* D3D = CDirect3D::Instance();

    Engine->Init();
    sConfig config;
    if(DoConfigWindow(&config) != NE_OK) return 0;
    CWindow window;
    window.Create("test", 800, 600, hInstance);
    D3D->Create(&config, window.GetHandle());

    return 0;
}

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

9

13.12.2009, 13:19

Zitat von »"dot"«

Zitat von »"drakon"«

Anyway würde ich ihm zu der anderen Variante raten.


Wenn, dann so jap. Wobei das Meyers Singleton eigentlich gleich ne Referenz zurückgeben kann statt nem Zeiger ;)

Ich würde aber generell dazu raten kein Singleton zu verwenden :p


Jup, habs wegen der Analogie so gelassen, weil er dann keinen Client Code ändern muss. ;)

Aber ja. Singletons sind (oft) nicht der Wege, den man gehen sollte.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

10

13.12.2009, 13:23

Zeig mal, was diese hier machen:

C-/C++-Quelltext

1
2
3
4
    CEngine* Engine = CEngine::Instance();
    CDirect3D* D3D = CDirect3D::Instance();

    Engine->Init(); 


btw:
Warum erbt CDirect3D von CEngine?!

Werbeanzeige