Toon posts:

[C++] Linker error: unresolved external symbol

Pagina: 1
Acties:
  • 129 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik ben een applicatie aan het maken die gebruik maakt van het singleton pattern. En ik gebruik wxWidgets als framework. Echter krijg ik op de static instantie van mijn object een link error, eveneens op de static mutex die de eventuele creatie van de instantie afschermt.

De headerfile:
C++:
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
#pragma once

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
   #include <wx/wx.h>
#endif

class debugWindow :
    public wxFrame
{
public:
    void fromServer(const wxString s);
    void toServer(const wxString s);
    void generalDebug(const wxString s);

    static debugWindow* Instance(void);

private:
    wxTextCtrl *_output;
    wxMutex s_mutex_output;
    static wxMutex s_lock_instance;
    static debugWindow* s_instance;

    debugWindow();
    debugWindow(const debugWindow&);
    debugWindow& operator=(const debugWindow&);
};


De cpp file:
C++:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "debugWindow.h"
#include "msn_global_config.h"

debugWindow::debugWindow():
wxFrame(NULL, -1, "Debug", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "Debug frame")
{   
    wxPanel *topPanel = new wxPanel(this);
    wxStaticBox *debugBox = new wxStaticBox(topPanel,-1,"Debug");
    wxStaticBoxSizer *debugSizer = new wxStaticBoxSizer(debugBox, wxHORIZONTAL);
    _output = new wxTextCtrl(topPanel,-1,"",wxDefaultPosition, wxSize(400,600),wxTE_MULTILINE|wxTE_RICH,wxDefaultValidator, "Debug");
    debugSizer->Add(_output,wxSizerFlags(1).Expand().Border(wxALL,5));
    topPanel->SetSizer(debugSizer);
    debugSizer->SetSizeHints(this);
}

void debugWindow::fromServer(const wxString s)
{
    s_mutex_output.Lock();
    _output->SetDefaultStyle(wxTextAttr(*wxGREEN));
    *_output << "S->C: " << s << "\n";
    s_mutex_output.Unlock();
}

void debugWindow::toServer(const wxString s)
{
    s_mutex_output.Lock();
    _output->SetDefaultStyle(wxTextAttr(*wxRED));
    *_output << "C->S: " << s << "\n";
    s_mutex_output.Unlock();
}

void debugWindow::generalDebug(const wxString s)
{
    s_mutex_output.Lock();
    _output->SetDefaultStyle(wxTextAttr(*wxBLACK));
    *_output << "Gen: " << s << "\n";
    s_mutex_output.Unlock();
}

debugWindow* debugWindow::Instance()
{
    if (s_instance == NULL){
        wxMutexLocker lock(s_lock_instance);
        if (s_instance == NULL){
            s_instance = new debugWindow();
        }
    }
    return s_instance;
}

debugWindow::debugWindow(const debugWindow&)
{
}

debugWindow& debugWindow::operator=(const debugWindow&)
{
    return *s_instance;
}


De link errors:
debugWindow.obj : error LNK2001: unresolved external symbol "private: static class wxMutex debugWindow::s_lock_instance" (?s_lock_instance@debugWindow@@0VwxMutex@@A)
debugWindow.obj : error LNK2001: unresolved external symbol "private: static class debugWindow * debugWindow::s_instance" (?s_instance@debugWindow@@0PAV1@A)
vc_mswd\msnclient.exe : fatal error LNK1120: 2 unresolved externals

Ik tast eigenlijk helemaal in't duister of't nu een wxWidgets of een C++-programmeer fout is of een bug in de linker (denk ik niet)? WxWidgets probleem lijkt me ook niet, want in die richting heb ik al gezocht. Als het een C++ programmeer fout is, de welke? Samengevat, ik zie zelfs niet waar het probleem eventueel zou kunnen liggen, laat staan waar ik kan zoeken.
Waar ik al gezocht heb: Google op de link error, maar daar was het probleem meestal een niet goed geinclude library. Maar ik ben er zeker van dat threads van wx zijn geinclude. (de methodes fromServer, toServer en generalDebug maakten al gebruik van die mutexes voor ik singleton pattern ging include, en die werkten perfect.)
Iemand nog verhelderende ideeën?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Standaard beginnersfout :). Static variabelen moet je, net als member functies, niet alleen declareren in de class maar ook definieren in een source file. Zo dus:

C++:
1
2
3
4
5
6
7
8
// je header
class MyClass
{
    static int bla;
};

// Je sourcefile:
int MyClass::bla;

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ja toen ik linker error en singleton las, alleen dat, dacht ik al meteen "oh static vergeten te definieeren" :)

Verwijderd

Topicstarter
Ok, dat was idd de oplossing.
Maar kan er iemand mij vertellen wat de reden is om dit zo te doen? Je declareert een type static, 1 keer in je headerfile, maar waarom moet je het dan nog eens in je sourcefile declarern ook?

Verder is het niet alleen een beginnersfout, maar ook eentje van iemand die het afgelopen jaar bijna enkel nog java heeft geschreven 8)7 Maar dit wijst me er wel op dat ik wat meer C++ moet schrijven!

  • TheNameless
  • Registratie: September 2001
  • Laatst online: 07-02-2025

TheNameless

Jazzballet is vet!

Verwijderd schreef op donderdag 01 september 2005 @ 15:49:
Ok, dat was idd de oplossing.
Maar kan er iemand mij vertellen wat de reden is om dit zo te doen? Je declareert een type static, 1 keer in je headerfile, maar waarom moet je het dan nog eens in je sourcefile declarern ook?

Verder is het niet alleen een beginnersfout, maar ook eentje van iemand die het afgelopen jaar bijna enkel nog java heeft geschreven 8)7 Maar dit wijst me er wel op dat ik wat meer C++ moet schrijven!
Volgens mij wordt hij in je source file geinitaliseerd (dus een waarde gegeven) en niet gedeclareerd :)

@edit: yup, ik heb gelijk volgens de msdn: http://msdn.microsoft.com...html/_pluslang_static.asp
code:
1
Static data members of classes must be initialized at file scope.


Je static variabele wordt dus geinitaliseerd naar 0 voor de duidelijkheid.

[ Voor 20% gewijzigd door TheNameless op 01-09-2005 16:06 ]

Ducati: making mechanics out of riders since 1946


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 01 september 2005 @ 15:49:
Ok, dat was idd de oplossing.
Maar kan er iemand mij vertellen wat de reden is om dit zo te doen? Je declareert een type static, 1 keer in je headerfile, maar waarom moet je het dan nog eens in je sourcefile declarern ook?
Waarom moet je een extern int blaat; ook nog ergens definieren? Waarom moet je een void bliep(); ergens een body geven? Als je met een groep vrienden afspreekt dat er eentje een BBQ meeneemt tijdens een weekendje weg, maar niemand heeft 'm uiteindelijk bij zich omdat ze dachten dat iemand anders 'm wel bij zich zou hebben, waar is de BBQ dan? :)

Je sourcefiles vormen in dit geval de groep vrienden, die static variabele is de BBQ. Érgens moet ie gedefinieerd worden, anders bestaat ie niet en gaat de linker klagen omdat ie geen vlees kan bakken.

[ Voor 14% gewijzigd door .oisyn op 01-09-2005 16:26 ]

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.

Pagina: 1