Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a namespace to make global functions, but getting multiply defined symbols error

These functions are Utility type things that most of my programs objects will use. I want to have them in a namespace and have them global. This namespace is defined in a header and then added to my precompiled header. However so far I have used the function from this namespace in 2 different objects and the compiler is throwing the multiply defined symbols error on these 2 objects.

namespace file

#ifndef UTILS_H
#define UTILS_H

#include <random>
#include <cmath>


namespace Utils
{
    extern int GetRandomBetween(int low, int high)
    {
        if (low < 0 || low >= high)
            return 0;
        int seed = high - low;

        return (rand() % seed) + low;
    }
};

#endif

and my precomp header

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

//#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <random>


#define SAFE_DELETE( p )       { if( p ) { delete ( p );     ( p ) = NULL; } }
#define SAFE_DELETE_ARRAY( p ) { if( p ) { delete[] ( p );   ( p ) = NULL; } }
#define SAFE_RELEASE( p )      { if( p ) { ( p )->Release(); ( p ) = NULL; } }
// TODO: reference additional headers your program requires here

#include "Utils.h"
#include "Manager.h" // this object uses utils
#include "Bot.h"    // this object uses utils
#include "LinkedList.h"
#include "Village.h"  // this object will use utils in the future

The linker error message:

Manager.obj : error LNK2005: "int __cdecl Utils::GetRandomBetween(int,int)" (?GetRandomBetween@Utils@@YAHHH@Z) already defined in Bot.obj stdafx.obj : error LNK2005: "int __cdecl Utils::GetRandomBetween(int,int)" (?GetRandomBetween@Utils@@YAHHH@Z) already defined in Bot.obj c:\users\lee\documents\visual studio 2010\Projects\AI\Debug\AI.exe : fatal error LNK1169: one or more multiply defined symbols found

it also maybe worth noting that in my Manager class header I forward declared Bot. Same with Village class header.

like image 941
EddieV223 Avatar asked Aug 05 '11 22:08

EddieV223


2 Answers

Your function definition (ie: the source code) should not be in a header. The reason you are getting multiple definitions is that extern cannot convert a function definition (the source code) into a function declaration (ie: just the prototype). So you need to do this:

Util.h:

namespace Utils
{
    int GetRandomBetween(int low, int high);
};

SomeSourceFile.cpp (probably Util.cpp):

namespace Utils
{
    int GetRandomBetween(int low, int high);
    {
        if (low < 0 || low >= high)
            return 0;
        int seed = high - low;

        return (rand() % seed) + low;
    }
};

Alternatively, you can declare the function inline in the header:

namespace Utils
{
    inline int GetRandomBetween(int low, int high)
    {
        if (low < 0 || low >= high)
            return 0;
        int seed = high - low;

        return (rand() % seed) + low;
    }
};

Though you should only use this for small functions.

like image 97
Nicol Bolas Avatar answered Oct 23 '22 02:10

Nicol Bolas


Manager.cpp and Bot.cpp both include Util.h

Because of this, when they are compiled, both object files export the symbol "GetRandomBetween". When the linker goes to combine these object files into an executable, it finds 2 instances of the function. The linker can't determine which one to use (and it doesn't understand that they are identical).

If you want to make the object files NOT export the symbol (so that you dont have a linker conflict), remove the extern keyword.

like image 22
J T Avatar answered Oct 23 '22 02:10

J T