Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global variables and linking problems

My mostly header based library makes use of a global variable placed in the library's namespace (BigNum). The definition of the variable is as follows:

namespace BigNum{
/**
* __Some lower powers of ten prestored for fast runtime lookup.__*/
const uintmax_t pten[20]={
1LU, 10LU, 100LU, 1000LU, 10000LU, 100000LU, ....
};
}

Everything works fine as long as I have this definition in my main.cpp file (really the only nonheader file my testing config has) and my headers have extern uintmax_t pten[]; in them (provided they also include cstdint, where uintmax_t is typedefined).

I would, however, like to have this definition elsewhere, so I created a global.cpp file with the above as its contents and made sure my Makefile linked it to the rest of the files. Interestingly enough, compiling with the definition of pten in both main.cpp and global.cpp works fine (I would have expected double definition errors), but removing the definition from main.cpp while leaving it in global.cpp leads to linking errors.

I checked the generated global.o and it does contain the pten symbol (its mangled form). Attempting to link main.o with global.o manually in either order fails.

Any ideas?

Additional info: Here's an elementary example demostrating the problem.

main.cpp

    #include <cstdint>
    #include <iostream>

    namespace BigNum{
    extern const uintmax_t pten[];
    }
    int main( int argc, const char *argv[] )
    {
        using namespace std;

        cout<<BigNum::pten[0]<<endl;
        return 0;
    }

global.cpp

    #include <cstdint>

    namespace BigNum{
    /**
     * __Some lower powers of ten prestored for fast runtime lookup.__
     */
    const uintmax_t pten[20]={
        1LU, 10LU, 100LU, 1000LU, 10000LU, 100000LU, 1000000LU, 10000000LU, 100000000LU, 1000000000LU, 10000000000LU, 100000000000LU, 1000000000000LU, 10000000000000LU, 100000000000000LU, 1000000000000000LU, 10000000000000000LU, 100000000000000000LU, 1000000000000000000LU, 10000000000000000000LU
    };
    }

Compilation:

  g++ -std=c++0x -c global.cpp -o global.o
  g++ -std=c++0x -c main.cpp -o main.o
  g++ -std=c++0x global.o main.o

 >main.o: In function `main':
 >main.cpp:(.text+0x12): undefined reference to `BigNum::pten'
 >collect2: ld returned 1 exit status
like image 590
PSkocik Avatar asked May 01 '26 01:05

PSkocik


1 Answers

Your code in global.cpp should be:

#include <cstdint>

namespace BigNum{
/**
 * __Some lower powers of ten prestored for fast runtime lookup.__
 */
extern const uintmax_t pten[]; //This should go in a common header file
const uintmax_t pten[20]={
    1LU, 10LU, 100LU, 1000LU, 10000LU, 100000LU, 1000000LU, 10000000LU, 100000000LU, 1000000000LU, 10000000000LU, 100000000000LU, 1000000000000LU, 10000000000000LU, 100000000000000LU, 1000000000000000LU, 10000000000000000LU, 100000000000000000LU, 1000000000000000000LU, 10000000000000000000LU
};
}

Check this guide: Normally, you would put extern const uintmax_t pten[]; in a separate common header file.

like image 145
Antonio Avatar answered May 02 '26 16:05

Antonio



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!