IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Problèmes de linker a la compilation.


Sujet :

C++

  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut Problèmes de linker a la compilation.
    Salut les C++,

    dans le cadre d'un tutoriel j'ai écrit un petit conteneur basé sur du C (Que je préfère au C++) en C++

    Vous trouverez le zip ici.

    Le zizip contient 4 fichiers:

    + MyArray.h

    + MyArray.cpp

    + main.cpp

    + Makefile

    Si je place le code qui devrai être dans main.cpp dans MyArray.cpp et que je compile avec un terminal

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $ c++ -std=c++11 -g -O2 MyArray.cpp
    Tout ce passe bien.

    ---

    Sinon si je place la fonction main dans le fichier main.cpp

    J'obtiens le traceback suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    g++  -Wall -pedantic -Wno-deprecated -Wno-deprecated-declarations     -g -O2 -std=c++11        -c src/MyArray.cpp -o src/MyArray.o 
    g++  -Wall -pedantic -Wno-deprecated -Wno-deprecated-declarations     -g -O2 -std=c++11        -c src/main.cpp -o src/main.o 
    In file included from src/main.cpp:1:0:
    src/./MyArray.h: In instantiation of ‘T& MyArray<T>::get_element(size_t) [with T = double; size_t = long unsigned int]’:
    src/main.cpp:26:23:   required from here
    src/./MyArray.h:37:48: warning: statement has no effect [-Wunused-value]
         T& get_element(const size_t index) { try { index < size ; return Array[index] ; } catch (std::out_of_range) { std::cerr << "index out of bounds" << std::endl ; } }  ;
                                                    ^
    g++  -Wall -pedantic -Wno-deprecated -Wno-deprecated-declarations     -g -O2 -std=c++11       -o ./bin/MyArray ./src/MyArray.o ./src/main.o  
    ./src/main.o*: Dans la fonction «*main*»*:
    /home/edward/Bureau/MyArray/src/main.cpp:9*: référence indéfinie vers «*MyArray<double>::MyArray(unsigned long, double)*»
    /home/edward/Bureau/MyArray/src/main.cpp:44*: référence indéfinie vers «*MyArray<double>::bubble_sort(bool)*»
    collect2: error: ld returned 1 exit status
    Makefile:480*: la recette pour la cible «*bin/MyArray*» a échouée
    make: *** [bin/MyArray] Erreur 1
    Et je ne comprends pas.

    ---

    Je me dis que cela doit être un problème de linker simplement a cause de make.

    Le problème ou plutot ce qui est bizarre est que:

    le traceback dit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ...
    { std::cerr << "index out of bounds" << std::endl ; } }  ;
    ...
    Alors que j'ai remplacer ce string : "index out of bounds" a été" remplacer par e.what() et que

    du coup la sortie est du coup très bizarre de ne pas voir comme traceback:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ...
    { std::cerr << e.what() << std::endl ; } }  ;
    ...
    A moins que make ai mis le traceback en cache ? ce que je fends car j'ai compiler les fichiers un par un en fichier objet et les ai linker !

    ---

    En espérant que cela soit une erreur interne du c++ ou de make.

    Merci pour votre aide.

    ---

    Note: Je suis en train d'écrire un gros tutoriel et j'espère que vous en serai, vous comprendrez après.

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    get_element est simplement affreux:

    - condition qui ne fait rien
    - try/catch pour afficher une erreur et la cacher de l’extérieur
    - capture de l'exception par copie
    - retour foireux en cas d'exception
    - variable des fois avec une majuscule en première lettre, des fois sans

    Mais bon: Pourquoi mes templates ne sont-ils pas reconnus à l'édition des liens ?

  3. #3
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    Dans MyArray.h, je lis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    template <typename T=int>
     
    class MyArray {
     
      private :
     
        size_t size=0 ;
     
        T *Array ;
     
      public :
     
        MyArray(void) { } ;
     
        MyArray(const size_t nb_elts, const T data=0) ;
     
        MyArray(const MyArray &arg) { arg.size = size ; arg.Array = Array ; }
     
        MyArray(const MyArray &&arg) { arg.size = size ; arg.Array = Array ; size=0 ; delete []Array ; }
     
        MyArray& operator = (const MyArray &arg) { arg.size = size ; arg.Array = Array ; }
     
        T& get_element(const size_t index) { try { index < size ; return Array[index] ; } catch (std::out_of_range) { std::cerr << "index out of bounds" << std::endl ; } }  ;
     
        size_t get_size(void) { return size ; }
     
        void bubble_sort(const bool ascending) ;
     
        bool is_sorted(const bool ascending) ;
     
        bool search_inside(const T key) ;
     
        T* begin(void) { return Array ; }
     
        T* end(void)   { return &Array[size] ; }
     
        ~MyArray(void) { free(Array) ; size=0 ; }
     
    };
    En ce qui concerne la gestion de la mémoire, il faut TOUT recommencer.

  4. #4
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    Merci pour les réponses.

    Il me semble savoir,

    car mon langage par défaut est le C et non le C++,

    que un fichier contenant un template doit être un en-tête, corriger moi si je me trompe.

    Pourquoi make affiche un traceback qui ne correspond pas a ce qui est écrit dans le code source:

    Concernant la méthode get_element(...) je l'ai remplacer en surchargeant l'opérateur d'indexation ([]).

    Je vous pris de développer vos propos concernant les problèmes la gestion de la mémoire, car j'ai corriger le destructeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ~MyArray(void) { delete []Array ; size=0 ; } ;

  5. #5
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    @Luke spywoker :
    Tu as corrigé le code de ton destructeur et tu m'as demandé plus d'explications à propos de la gestion de la mémoire.

    Voici donc un exemple d'implémentation du constructeur de copie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <cstddef> // size_t
     
    template<class T>
    class TableauSimple
    {
    public:
    	// ...
    	TableauSimple(const TableauSimple<T>& other) :
    		m_data{other.m_size > 0 ? new T[other.m_size] : nullptr},
    		m_size{other.m_size}
    	{
    		try {
    			for(size_t k = 0; k < m_size; ++k)
    				m_data[k] = other.m_data[k];
    		} catch(...) {
    			delete[] m_data;
    			throw;
    		}
    	}
    	// ...
    private:
    	T*     m_data;
    	size_t m_size;
    };
    L'implémentation que je viens d'écrire est simple, mais a quelques défauts, dont le suivant : Le type T est obligé d'avoir un constructeur par défaut et une affectation de copie.

    Il est possible d'éviter ce défaut, mais alors l'implémentation devient plus technique et nécessite davantage de prérequis en C++.
    Voici une implémentation dans laquelle le constructeur de copie du tableau a seulement besoin que T possède un constructeur de copie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    #include <cassert>
    #include <cstddef>     // size_t
    #include <type_traits> // std::aligned_storage
     
    template<class T>
    class TableauPlusTechnique
    {
    private:
    	using Cell = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
    public:
    	// ...
    	TableauPlusTechnique(const TableauPlusTechnique<T>& other) :
    		m_data{other.m_size > 0 ? new Cell[other.m_size] : nullptr},
    		m_size{0}
    	{
    		try {
    			for(size_t k = 0; k < other.m_size; ++k)
    			{
    				// appel explicite du constructeur de copie de T
    				// à l'adresse m_data + k
    				new(m_data + k) T{other.get_element(k)};
     
    				++m_size;
    			}
    		} catch(...) {
    			destroy();
    			throw;
    		}
    	}
    	~TableauPlusTechnique()
    	{
    		destroy();
    	}
    	// ...
    private:
    	void destroy() {
    		for(size_t k = 0; k < m_size; ++k) {
    			size_t index = m_size - 1 - k;
    			get_element(index).~T(); // appel explicite du destructeur de T
    		}
    		delete[] m_data;
    	}
    	const T& get_element(size_t index) const {
    		assert(index < m_size);
    		return *reinterpret_cast<const T*>(m_data + index);
    	}
    	T& get_element(size_t index) {
    		assert(index < m_size);
    		return *reinterpret_cast<T*>(m_data + index);
    	}
    	Cell*  m_data;
    	size_t m_size;
    };

  6. #6
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    Merci pour votre réponse précise et technique.

    J'ai des connaissances de base en C++ malgré que cela fait quelques années (3-4 ans) que j'ai démarrer le C++,

    je reste a mouliner en C.

    Tu l'aura sans doute remarquer dans la construction de mon code auquel il faut bien sur quelque modification comme détruire

    le tableau temporaire dans la méthode bubble_sort, ou j'ai changer le bcopy(...) en memcpy (...) afin de pas utiliser les les en-tête du C.

    Ce code servira et sera sans nul doute reformater si vous me suivez dans mon projet...

    J'espère que vous en serez.

    P.S: Bien sur que il faut mettre les templates dans les en-tête.

    Par contre la sortie bizarre je ne comprends pas.

  7. #7
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Concernant les templates et les en-têtes, la réponse est ca dépend de pourquoi.

    Une template permet de créer automatiquement des fonctions identiques pour des types distincts (en gros).

    La définition de la template est requise à chaque instanciation implicite (à chaque usage, en gros).
    Cela signifie qu'elle doit être définie partout où elle est utilisée.

    Si tu n'en as besoin que dans un seul fichier, tu n'as pas besoin de la définir dans un en-tête.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de linker pour cross compile raspberry
    Par johnvox dans le forum Autres éditeurs
    Réponses: 0
    Dernier message: 08/04/2014, 10h11
  2. Problème pour linker la lib d'une Dll
    Par damien99 dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 23/02/2006, 23h20
  3. Problème de linker à la compilation
    Par screeminelle dans le forum C++
    Réponses: 8
    Dernier message: 27/10/2005, 16h20
  4. Problème à l'exécution avec wxWindows (compilé avec BCC55)
    Par ShootDX dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 14/11/2003, 18h04
  5. [Debutant] Problème du linker [Dev-c++4]
    Par Macdir dans le forum Dev-C++
    Réponses: 3
    Dernier message: 30/05/2003, 20h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo