2013-06-23 7 views
3

Ma bibliothèque principalement en-tête utilise une variable globale placée dans l'espace de nom de la bibliothèque (BigNum). La définition de la variable est la suivante:Variables globales et problèmes de liaison

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

Tout fonctionne bien aussi longtemps que j'ai cette définition dans mon fichier main.cpp (vraiment déposer le seul nonheader ma config de test a) et mes têtes ont extern uintmax_t pten[]; dans eux (à condition qu'ils incluent également cstdint, où uintmax_t est typedefined). Je voudrais, cependant, avoir cette définition ailleurs, donc j'ai créé un fichier global.cpp avec ce qui précède en tant que son contenu et fait en sorte que mon Makefile l'a lié au reste des fichiers. Il est intéressant de noter que compiler avec la définition de pten dans les deux main.cpp et global.cpp fonctionne bien (j'aurais attendu des erreurs de définition double), mais supprimer la définition de main.cpp tout en le laissant dans global.cpp conduit à des erreurs de liaison .

J'ai vérifié le global.o généré et il contient le symbole pten (sa forme mutilée). Tenter de lier main.o avec global.o manuellement dans l'un ou l'autre ordre échoue.

Des idées?

Informations supplémentaires: Voici un exemple élémentaire illustrant le problème.

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 
+2

* Lier * erreurs? Vous ne nous en dites pas beaucoup, mais si ce que vous nous dites est exact, je ne peux pas reproduire cette erreur ni la comprendre. Si vous nous donnez un exemple complet minimal, nous pourrions être en mesure de l'effacer. – Beta

+0

Mes pouvoirs de débogage télépathique m'informent que vous n'avez pas la déclaration d'en-tête de l'extern dans l'espace de noms BigNum ?? – Petesh

+0

@Beta Exemple ajouté. Merci d'avoir regardé ça. – PSkocik

Répondre

2

Votre code global.cpp devrait être:

#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 
}; 
} 

Vérifiez this guide: Normalement, vous mettriez extern const uintmax_t pten[]; dans un fichier d'en-tête commune séparée.

+0

Merci. Cela fonctionne de toute façon: avec un extern dans la définition et une déclaration externe dans main.cpp ou avec une définition non externe et une définition externe dans les deux fichiers. J'avais un en-tête partagé avec une déclaration externe de pten, mais je ne l'incluais pas dans global.cpp. Si j'avais, cela aurait résolu le problème. ;-) – PSkocik

-1

Problème résolu. Il s'avère que toutes les variables globales sont, contrairement aux fonctions, invisibles à partir d'autres unités de compilation. Pour les rendre visibles, le mot-clé extern doit également être utilisé dans leur définition (dans global.cpp).

+1

Ceci est * impossible *. Ne confondez pas déclaration avec définition. Lorsque vous utilisez 'extern' est toujours une déclaration. Où définissez-vous * votre variable? Veuillez lire [this] (http://en.wikipedia.org/wiki/External_variable). – Antonio

+0

"Toutes les variables globales sont, contrairement aux fonctions, statiques et donc invisibles à partir d'autres unités de compilation" - cette déclaration est * false *. –

+0

@ ThorX89 Le code ajoutant simplement 'extern' fonctionne un peu par hasard, essentiellement parce que vous initialisez/allouez de la mémoire pour la variable. – Antonio