[C++] Error Singleton Class in DLL

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Robbiedobbie
  • Registratie: Augustus 2009
  • Laatst online: 16-09 19:30
Hallo Allemaal,

Ik wil voor een applicatie een globale log maken. Dit moet werken in zowel de applicatie als in iedere DLL die wordt ingeladen. Daarom wilde ik een singleton class in een DLL gebruiken.
Helaas krijg ik dit niet werkend.

Mijn class ziet er als volgt uit (versimpeld, nog steeds zelfde probleem):
C++: Lib_SettingBar.h
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class LIB_SETTINGBAR_API CLib_SettingBar {
public:
    
    static CLib_SettingBar& GetInstance(void);
    HRESULT WriteConsoleEntry(string);
    
private:
    
    CLib_SettingBar();
    CLib_SettingBar(const CLib_SettingBar&);            // Prevent copy-construction
    CLib_SettingBar& operator=(const CLib_SettingBar&); // Prevent assignment
    FILE * f;
    // TODO: add your methods here.
};


C++: Lib_SettingBar.cpp
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "Lib_SettingBar.h"

CLib_SettingBar::CLib_SettingBar()
{
    string filename = "Console_Log.txt";
    fopen_s(&f, filename.c_str(), "wt");
}

CLib_SettingBar &CLib_SettingBar::GetInstance()
{
    static CLib_SettingBar Instance;
    return Instance;
}

HRESULT CLib_SettingBar::WriteConsoleEntry(string Message)
{
    fprintf(f, "%s", Message.c_str() );
    fclose(f);
    return S_OK;
}


In mijn applicatie laadt ik de DLL in, zonder problemen.
Dan roep ik in de main functie van mijn applicatie een functie uit de class aan op deze manier:
C++:
1
CLib_SettingBar::GetInstance().WriteConsoleEntry(temp);

Hierbij is temp een string. Als ik dit debug, wordt netjes de functie aangeroepen zoals verwacht. Echter, zodra return wordt aangeroepen in WriteConsoleEntry, wordt er een breakpoint gezet door windows.
In de output van Visual Studio zie ik dit staan:
Invalid address specified to RtlValidateHeap( 02030000, 01F34D88 )

Zelf denk ik dat er iets fout is met een type van een variabele wat wordt doorgegeven. Ik heb hier 2 dagen naar zitten zoeken, maar kan niet vinden wat er fout is. Misschien dat iemand anders wel ziet wat hier fout aan is.

PS: Ik moet toegeven dat ik nog niet lang met c++ werk.

Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Als je met DLLs werkt, dan is het verreweg het handigst om ook de Visual C++ DLL te gebruiken. Anders krijgt elke DLL en de EXE een eigen kopie van de Visual C++ classes. Het gevolg is dan dat het doorgeven van een object van de ene DLL naar de andere onbetrouwbaar is. (Nieuwere versies doen het wel iets beter - gebruik je toevallig nog VC6?)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • Robbiedobbie
  • Registratie: Augustus 2009
  • Laatst online: 16-09 19:30
Ik maak gebruik van Visual Studio 2010. Ik maak de DLLs gewoon aan door een nieuw DLL project in de solution aan te maken. Naar mijn weten worden deze classes niet in iedere DLL opgeslagen?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het hangt er vanaf of je statisch of dynamisch linkt met de runtime (project properties -> C++ -> Code Generation -> Runtmie Library, en kies daar voor een variant met "DLL" erin), maar dat staat meestal by default wel goed.

Een andere mogelijkheid is dat je een release DLL in een debug applicatie laadt of andersom. In debug is de memory layout van de standaard classes anders omdat er heel veel debug informatie in zit (om bijv. te kunnen controleren of een iterator wel bij een bepaalde container hoort, etc.)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Robbiedobbie
  • Registratie: Augustus 2009
  • Laatst online: 16-09 19:30
De DLL en de EXE zijn allebei een debug-build. De runtime is bij beide ingesteld op Multi-threaded Debug DLL tijdens een debugbuild en op Multi-threaded DLL bij een release build.

Ik denk niet dat deze fout veroorzaakt wordt doordat de DLL verkeerd gebuild wordt, aangezien andere DLLs die op dezelfde manier gebuild worden, wel werken met alle functies. Het enige verschil is dat deze DLL een singleton-class exporteert. Ik denk dat ik een fout heb gemaakt bij de singleton-class, maar vinden doe ik hem niet. Ook een nachtje slapen en daarna verder kijken heeft me nog niet verder geholpen :P

[ Voor 16% gewijzigd door Robbiedobbie op 20-02-2012 11:29 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Weet je zeker dat dat het enige verschil is? Is het verschil ook niet dat jij een std::string by value passed, maar dat andere DLLs helemaal geen std::string verwachten of deze als (const) reference accepteren?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Robbiedobbie
  • Registratie: Augustus 2009
  • Laatst online: 16-09 19:30
Nu je het zegt...
Ik dacht een andere class te hebben die ook een string accepteerde, maar nu ik daar nog eens naar ben gaan zoeken, zag ik dat ik daar een char array gebruik, ipv een string. Ik ga eens proberen of dit mijn fout is.

EDIT: Net geprobeerd, probleem opgelost door een char array te gebruiken. Ik snap niet hoe ik hier zo lang over heb gezeten, zonder dit zelf op te merken.
Bedankt voor de hulp!!

[ Voor 28% gewijzigd door Robbiedobbie op 20-02-2012 11:39 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nou ja, dat is op zichzelf sowieso nog geen fout. De issue is dat bij een pass by value de caller verantwoordelijk is voor de construction van het object, en de callee voor de destruction. Als de DLLs verschillende heaps gebruiken en de class doet memory allocaties, dan kan dat dus fout gaan omdat de allocaties van een andere heap worden gedaan dan de deallocaties. Een andere opties is dat de classes fysiek verschillend zijn tussen de DLL en de exe. Als de DLL een extra pointer aan het eind van de class verwacht waar debug info in staat wat ie vervolgens vrij gaat geven, dan krijg je wederom dit soort errors.

Je kunt er wel een pass by reference van maken, wat sowieso aan te raden is omdat het niet nodig is dat de callee zijn eigen kopie heeft, maar dat is slechts symptoombestreiding.

Ik zou even controleren of de memory layout van een std::string in de EXE en die in de DLL wel identiek zijn. Je kan daarvoor gebruik maken van een ongedocumenteerde compiler optie.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Robbiedobbie
  • Registratie: Augustus 2009
  • Laatst online: 16-09 19:30
Ik had een pass by value gedaan omdat ik in de oorspronkelijke functie (deze was versimpeld) direct een bewerking op de string toepas. Daarom had ik sowieso een eigen kopie nodig.
De reden waarom ik zeg dat ik niet snap dat ik hier zolang op heb gezeten, is omdat ik ooit een vergelijkbare error in een andere class heb gehad (ook met een string), maar dat ik die toen heb opgelost. Daar had ik nu niet meer aan gedacht.

Ik zal eens kijken naar die link. Bedankt voor de hulp!
Pagina: 1