Linker error on something that was extern'd

Hi Guys,

I'm getting a linker error in Release build only in VS2008. The linker settings are identical in Release and Debug.

1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@ABV01@@Z) already defined in libsimcom.lib(timer.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::~basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in libsimcom.lib(timer.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >(char const *)" (??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z) already defined in libsimcom.lib(timer.obj)
1>msvcprt.lib(MSVCP90.dll) : error LNK2005: "public: char const * __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::c_str(void)const " (?c_str@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEPBDXZ) already defined in libsimcom.lib(timer.obj)


The problem is that g_list (line 28) is apparently being defined multiple times, though I am using extern. The code below is in a statically linked library (libsimcom.lib). g_list is supposed to be shared between each .obj that uses it, so that anyone can use SetAfterDelay() to "add" an object to the list and the executive module can use ManageDelays() to follow-up on each object. Does anyone have an idea?

timer.h
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
#ifndef TIMER_H
#define TIMER_H

#include <vector>

namespace wa7vasxh // Arbitrary strange name to avoid conflicts and to protect the inner members from being in global scope
{                  // These functions are not intended for use outside of this library
    struct CountDownObject
    {
    public:
        float m_timeLeft;
        virtual bool timeExpired(float dt) = 0;
    };

    template <typename T>
    class DelayObject : public CountDownObject
    {
    private:
        //...
    public:
        DelayObject( T* lpLabelAddress, float delay, T target) { /*...*/ }

        // Decrements the timer and sets everything if required
        // Returns TRUE if the time has expired.  If this has happened, clean up DelayObject as it's useless now.
        virtual bool timeExpired(float dt) { /*...*/ }
    };

    extern std::vector<CountDownObject*> g_list; // When other .objs include this file, they have a problem right here! 
};

template <typename T>
void SetAfterDelay( T* lpLabelAddress, float delay, T target = T(1) )
{
    wa7vasxh::g_list.push_back(new wa7vasxh::DelayObject<T>(lpLabelAddress, delay, target) );
}

void ManageDelays(float dt);

#endif //TIMER_H 


timer.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <mylib/timer.h>

namespace wa7vasxh 
{
    std::vector<CountDownObject*> g_list;
}

void ManageDelays(float dt)
{
    for ( std::vector<wa7vasxh::CountDownObject*>::iterator it = wa7vasxh::g_list.begin(); it != wa7vasxh::g_list.end();)
    {
        if ( (*it)->timeExpired(dt) )
        {
            delete *it;
            it = wa7vasxh::g_list.erase(it);
        }
        else
        {
            ++it;
        }
    }
}
Last edited on
closed account (Dy7SLyTq)
extern doesnt resolve scope issues. :: does that. extern is to show global variables across multiple headers i believe
I dont see any errors relating to g_list, how did you come to that conclusion?

I do see 4 errors about std::string though, constructor/destructor/c_str() (actually 2 constructors)

try running LIB / LIST to see what is in your libsimcom.lib, i think you will find stdlib has been statically linked with it and that is causing the clash with MSVCP90.dll.

from the errors you have listed it looks like std::string appears in your current application that you are building and also in your other project libsimcom.lib

edit...
it could also be linker options in those 2 projects check out /MT and /MD here...http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=vs.80).aspx
Last edited on
Thanks, I'll figure out my problems with the statically linked standard library. This answers my question! I just assumed it was a problem with g_list because that was the only object that was declared.
Topic archived. No new replies allowed.