2009-03-19 5 views
1

Salutations Tout le monde.Erreur de référence de symbole UNIX

Je suis actuellement en train d'essayer de compiler un programme multilingue (C, C++ et FORTRAN) en utilisant des compilateurs GNU sous UNIX (g ++, gcc & f77 respectivement).

Toutes mes sources compilent en objets sans erreur mais je rencontre un symbole d'erreur faisant référence car ils sont liés, comme indiqué ci-dessous:

f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \ 
     SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\ 
     BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o 
NOTICE: Invoking /usr/bin/f90 -f77 -ftrap=%none -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o 
Undefined      first referenced 
symbol        in file 
_Znwj        SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEED1Ev SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEEC1Ev SA.o 
_ZNKSsixEj       main.o 
_ZNSolsEPFRSoS_E     SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode SA.o 
_ZNSolsEd       SA.o 
_ZNSolsEi       SA.o 
__cxa_end_catch      SA.o 
__cxa_begin_catch     SA.o 
_ZdlPv        SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE7is_openEv SA.o 
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c SA.o 
_ZSt4cerr       SA.o 
_ZSt4cout       SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE5closeEv SA.o 
_ZNSt8ios_base4InitD1Ev    main.o 
_ZNSt8ios_base4InitC1Ev    main.o 
_ZNKSt9basic_iosIcSt11char_traitsIcEEntEv SA.o 
__gxx_personality_v0    main.o 
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc SA.o 
__cxa_rethrow      SA.o 
_ZNKSs4sizeEv      main.o 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ SA.o 
ld: fatal: Symbol referencing errors. No output written to SlowDynamic.exe 
*** Error code 1 
make: Fatal error: Command failed for target `SlowDynamic.exe' 

Avec le Makefile Après:

products: SlowDynamic.exe 

SlowDynamic.exe: main.o SA.o mersenne.o CFE.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o MA_57.o blas.o MA_57_Depend.o Metis.o 
    f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \ 
     SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\ 
     BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o 

main.o: main.cpp 
    g++ -c -o main.o main.cpp 

SA.o: SA.cpp 
    g++ -c -o SA.o SA.cpp 

mersenne.o: mersenne.cpp 
    g++ -c -o mersenne.o mersenne.cpp 

CFE.o: CFE.c 
    gcc -c -o CFE.o CFE.c 

MA_57.o: MA_57.f 
    f77 -c -o MA_57.o MA_57.f 

blas.o: blas.f 
    f77 -c -o blas.o blas.f 

MA_57_Depend.o: MA_57_Depend.f 
    f77 -c -o MA_57_Depend.o MA_57_Depend.f 

Metis.o: Metis.f 
    f77 -c -o Metis.o Metis.f 

BCs.o: BCs.c 
    gcc -c -o BCs.o BCs.c 

EMatrix.o: EMatrix.c 
    gcc -c -o EMatrix.o EMatrix.c 

Numbering.o: Numbering.c 
    gcc -c -o Numbering.o Numbering.c 

KMatrix.o: KMatrix.c 
    gcc -c -o KMatrix.o KMatrix.c 

Solve.o : Solve.c 
    gcc -c -o Solve.o Solve.c 

clean: 
    rm *.o Main.exe *.gpi 

Je lisez que c'est généralement la faute des bibliothèques manquantes. Je sais que le code FORTRAN C & compile bien séparément (bibliothèques respectives incluses) comme le code C++ lorsqu'il est compilé seul. Cela m'amène à croire que c'est l'interface entre les deux programmes qui provoque l'erreur. Malheureusement, j'ai peu ou pas d'expérience de débogage de ce genre de problème et sans aucun indice de l'éditeur de liens, il est difficile d'aller de l'avant. Je vais inclure les parties nécessaires de mon programme qui traitent de l'interface entre les deux côtés du programme.

D'abord la partie C++: SA.h, SA.cpp

SA.h:

class SimAnneal { 
    ... 
    std::vector<float> DensityArray; 
    std::vector<float> EnergyArray; 
    public 
    double ObjFunction(); 
    ... 
} 

SA.ccp:

#include <math.h> 
#include <iostream> 
#include <fstream>   
#include <time.h>   
#include <vector> 
#include "SA.h" 
#include "CFE.h" 
#include "randomc.h" //Includes mersenne.cpp 

double SimAnneal::ObjFunction() 
{ 
    CFE(&DensityArray[0], &EnergyArray[0]); 

     // sends pointers of both arrays to CFE.c and modifies EnergyArray as 
     // shown in CFE.c 

    double SumStrainEnergy = 0; 

    for (int i = 0; i < EnergyArray.size(); i++) 
    { 
     SumStrainEnergy += EnergyArray[i]; //Effectively sum of array 
               //engy[] from CFE.c 
    } 

    return SumStrainEnergy; 
} 

En second lieu la partie C/Fortran: CFE .h, CFE.c

CFE.h:

#ifdef __cplusplus 
extern "C" { 
#endif 

void CFE(float density[], float energy[]); 

#ifdef __cplusplus 
} 
#endif 

CFE.c:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#include "BCs.h" 
#include "EMatrix.h" 
#include "Numbering.h" 
#include "KMatrix.h" 
#include "fg_types.h" 
#include "Solve.h" 

void CFE(float density[], float energy[]) 
{ 
    ...stuff... 

    float * dens; 
    dens = density; //pass pointer of array density[0] in SA.cpp to CFE.c 

    ...more stuff.... 

    float * engy; 
    engy = energy; //pass pointer of array energy[0] in SA.cpp to CFE.c 

    ***Modify engy in some respects****  
} 

Essentiellement, le ObjFunction dans SA.cpp est appelé dans main.cpp, qui contient main().

Y a-t-il un défaut visible?

Y a-t-il un moyen de demander à l'éditeur de liens d'indiquer quelles sont les causes/l'origine de l'erreur dans la liaison?

Toute aide sera très appréciée.

Merci.

+++ EDIT: modifier verbeux +++

birch $ g++ -v Hello.cpp 
Reading specs from /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/specs 
Configured with: /sfw10/builds/build/sfw10-patch/usr/src/cmd/gcc/gcc-3.4.3/configure --prefix=/usr/sfw --with-as=/usr/ccs/bin/as --without-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-languages=c,c++ --enable-shared 
Thread model: posix 
gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath) 
/usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/cc1plus -quiet -v Hello.cpp -quiet -dumpbase Hello.cpp -mcpu=v7 -auxbase Hello -version -o /var/tmp//cc2JwHRb.s 
ignoring nonexistent directory "/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/include" 
#include "..." search starts here: 
#include <...> search starts here: 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/sparc-sun-solaris2.10 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/backward 
/usr/local/include 
/usr/sfw/include 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/include 
/usr/include 
End of search list. 
GNU C++ version 3.4.3 (csl-sol210-3_4-branch+sol_rpath) (sparc-sun-solaris2.10) 
     compiled by GNU C version 3.4.3 (csl-sol210-3_4-branch+sol_rpath). 
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 
Hello.cpp:6:2: warning: no newline at end of file 
/usr/ccs/bin/as -V -Qy -s -xarch=v8 -o /var/tmp//ccvAshv7.o /var/tmp//cc2JwHRb.s 
/usr/ccs/bin/as: Sun Compiler Common 10 Patch 09/04/2007 
/usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/collect2 -V -R/usr/sfw/lib -Y P,/usr/ccs/lib:/usr/lib -Qy /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crt1.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crti.o /usr/ccs/lib/values-Xa.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtbegin.o -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3 -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/lib -L/usr/ccs/lib -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../.. /var/tmp//ccvAshv7.o -lstdc++ -lm -R/usr/sfw/lib -lgcc_s -lgcc -lc -R/usr/sfw/lib -lgcc_s -lgcc -lc /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtend.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtn.o 
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.490 

Répondre

4

Certains de ces symboles non définis clairement liés à des classes C++ standard (à savoir de ostream).

Vous devez vous assurer que vous avez au moins la bibliothèque C++ liée (-lstdC++).

Pour déboguer plus:

  1. Run F77, g ++, etc, en mode bavard (-v) avec des programmes de langue unique et voir quelles bibliothèques le compilateur inclut automatiquement dans la phase de lien pour chaque langue

  2. Pour les symboles qui se trouvent dans votre propre code, utilisez nm pour examiner à la fois les déclarations de langue natives et les invocations non natives pour déterminer leur incompatibilité. Il existe des règles concernant les préfixes de soulignement, etc., qui sont couramment appliquées.

(Pour autant que je me souvienne, mais il y a 15 ans que je Linked C et Fortran, symboles C sont toujours en interne préfixées par un trait de soulignement, mais les symboles ne sont pas Fortran).

+0

L'écriture dans -lg ++ directement après -lgcc_s ne le fait pas. Je tente de localiser le fichier comme vous l'avez dit en exécutant le script hello world via l'éditeur de liens en mode verbeux. Il est indiqué -lgcc et -lc mais le premier n'est pas trouvé. Ajout du commentaire détaillé en tant que modification. – Raugnar

+0

Vous voulez -lstdC++, pas -lg ++ –

+0

A la vôtre, ça l'a fait. Fulled compilé! – Raugnar

2

Le problème principal est que vous faites l'étape de liaison avec le compilateur F77, qui ne lie pas dans la bibliothèque standard C++ par défaut. Comme l'a dit Alnitak, spécifiez -lg ++ explicitement lors de la liaison pour l'obtenir. De plus, si vous appelez des fonctions C++ du code C (ou du code F77), assurez-vous d'inclure les prototypes de ces fonctions dans un bloc externe "C" {} afin que leur nom de symbole apparaisse dans le standard Formulaire C, plutôt que la forme C++ mutilé (cela vous empêche de certaines choses, cependant, comme la surcharge). Voir here pour plus d'informations.

0

Habituellement, vous devez lier un programme contenant du code C++ avec le compilateur C++, en ajoutant les bibliothèques Fortran et C à la ligne de liaison. De plus, le conseil standard est de faire le programme main() C++, ou Fortran, puisque les séquences de démarrage pour C++ sont différentes. Faites le code Fortran dans une fonction que vous appelez d'une main C++ minimale.

int main(void) // Assuming no argument handling - probably incorrect 
{ 
    return(fortran_main_program()); 
} 
Questions connexes