Domanda

Ho tre file di intestazione nel mio progetto che descrivono gli oggetti Rational, Complex, e RubyObject.I primi due sono i modelli.Tutti possono essere interconverted utilizzando costruttori di copia, che sono definiti nel file di intestazione, tranne quelli che costruire Rational e Complex da const RubyObject&s, che sono definiti in un file di origine.

Nota: Tali definizioni sono lì per necessità.Se tutti vai nelle intestazioni, si ottiene dipendenza circolare.

Un po ' indietro, mi sono imbattuto in alcuni simboli non risolti gli errori con i due costruttori di copia definito nel file di origine.Sono stato in grado di includere nel file di origine la seguente funzione

void nm_init_data() {
    nm::RubyObject obj(INT2FIX(1));
    nm::Rational32 x(obj);
    nm::Rational64 y(obj);
    nm::Rational128 z(obj);
    volatile nm::Complex64 a(obj);
    volatile nm::Complex128 b(obj);
}

e poi chiamata nm_init_data() dalla libreria il punto di ingresso principale file di origine.Facendo così costretto questi simboli per essere collegati correttamente.

Purtroppo, ho recentemente aggiornato il GCC e gli errori sono dietro.In realtà, sembra avvenire in modo leggermente diverso luogo con GCC 4.6 (ad esempio, Travis-CI).

Ma non è una versione del problema specifico (come avevo pensato prima).La vediamo su Travis CI del sistema basato su Ubuntu, che corre GCC 4.6.Ma non ci vedo su una macchina Ubuntu con GCC 4.8.1 o 4.8.2.Ma noi fare vedere su di un Mac OS X macchina con 4.8.2 — e non è la stessa macchina con 4.7.2.Spegnimento di ottimizzazione non sembra aiutare.

Se corro nm sulla mia libreria, il simbolo è sicuramente indefinito:

$ nm tmp/x86_64-darwin13.0.0/nmatrix/2.0.0/nmatrix.bundle |grep RationalIsEC1ERKNS
                 U __ZN2nm8RationalIsEC1ERKNS_10RubyObjectE
00000000004ca460 D __ZZN2nm8RationalIsEC1ERKNS_10RubyObjectEE18rb_intern_id_cache
00000000004ca458 D __ZZN2nm8RationalIsEC1ERKNS_10RubyObjectEE18rb_intern_id_cache_0

Io non sono sicuro perché ci sono due voci definite che sono subordinati al undefined symbol, ma anche io non so quanto mi piacerebbe che su compilatori.

Sembra anche il costruttore di copia è un simbolo non definito per ogni versione di Rational modello:

__ZN2nm8RationalIiEC1ERKNS_10RubyObjectE
__ZN2nm8RationalIsEC1ERKNS_10RubyObjectE
__ZN2nm8RationalIxEC1ERKNS_10RubyObjectE

"Beh, questo è strano", ho pensato."Complex64 e Complex128 sono anche chiamati in che nm_init_data funzione, ma entrambi hanno di risolvere correttamente e non sono riportati nel nm -u in uscita". Così ho provato ad aggiungere volatile prima di Razionale copia di costruzione, e, pensando che forse il compilatore è stato ottimizzazione qualcosa non vogliamo ottimizzato.Ma questo non risolvere il problema o, purtroppo.Questo ha fatto, con un avvertimento:

void nm_init_data() {
  volatile VALUE t = INT2FIX(1);
  volatile nm::RubyObject obj(t);
  volatile nm::Rational32 x(const_cast<nm::RubyObject&>(obj));
  volatile nm::Rational64 y(const_cast<nm::RubyObject&>(obj));
  volatile nm::Rational128 z(const_cast<nm::RubyObject&>(obj));
  volatile nm::Complex64 a(const_cast<nm::RubyObject&>(obj));
  volatile nm::Complex128 b(const_cast<nm::RubyObject&>(obj));
}

L'avvertenza è che ora ho lo stesso identico errore, ma per oggetti Complessi invece.Argh!

dyld: lazy symbol binding failed: Symbol not found: __ZN2nm7ComplexIdEC1ERKNS_10RubyObjectE
  Referenced from: /Users/jwoods/Projects/nmatrix/lib/nmatrix.bundle
  Expected in: flat namespace

dyld: Symbol not found: __ZN2nm7ComplexIdEC1ERKNS_10RubyObjectE
  Referenced from: /Users/jwoods/Projects/nmatrix/lib/nmatrix.bundle
  Expected in: flat namespace

Questo è completamente assurdo.Qui ci sono le definizioni per entrambe queste funzioni, nello stesso file sorgente del nm_init_data() funzione:

namespace nm {
  template <typename Type>
  Complex<Type>::Complex(const RubyObject& other) {
    // do some things
  }

  template <typename Type>
  Rational<Type>::Rational(const RubyObject& other) {
    // do some other things
  }
} // end of namespace nm

Suggerimento: Una cosa che è importante da ricordare è che l'errore non si verifica quando nm_init_data() viene chiamato (cioè, quando la libreria viene caricata).Succede molto più tardi, durante un'altra chiamata a questi fastidiosi funzioni.

Come posso risolvere questo problema una volta per tutte, e altri piace?

È stato utile?

Soluzione

Si sostengono le seguenti, di cui io dubito.

Tali definizioni sono lì per necessità.Se vanno tutti nelle intestazioni, si ottiene dipendenza circolare.

Nella maggior parte dei casi è possibile risolvere tale circolare entanglement, separando il tuo codice in un ulteriore .hpp file, che è incluso insieme con la definizione della classe che contiene le definizioni di modello qualsiasi bisogno.

Se il codice ha una vera dipendenza circolare, potrebbe non compilare.Di solito, se il tuo dipendenze sembrano essere circolare, è necessario guardare più da vicino e scendere a livello di metodo e di controllare quali di essi richiede entrambi i tipi per la compilazione.

Quindi potrebbe essere che i tuoi tipi di utilizzo di ogni altro, quindi compilare tutto in uno .file cpp (ad es.via tre .hpp include).O ci sono solo puntatore a un altro tipo, quindi utilizzare avanti le dichiarazioni di garantire che tutti i modelli sono stati risolti.O di terzi, avete qualche metodo che dipendono in avanti e alcuni che dipendono indietro, poi mettere il tipo in un file, gli altri tipo in un altro, e si sono di nuovo bene.

Inoltre, sembra che si dovrebbe utilizzare un futuro di dichiarazione per gli elementi mancanti.Mi sarei aspettato qualcosa come il seguente, dopo la definizione della funzione.E. g.:

template nm::Complex<nm::RubyObject>::Complex(const nm::RubyObject& other);

Altri suggerimenti

Rational, Complex...sono i modelli

costruttori di copia...sono definiti nel file di intestazione, tranne quelli che costruire Rational e Complex da const RubyObject&s, che sono definiti in un file di origine.

E qui sta il problema.Dal Rational e Complex sono i modelli, tutti i loro metodi hanno bisogno di essere disponibile nel file di intestazione.

Se non lo sono, allora si potrebbe a volte essere in grado di ottenere via con esso, a seconda dell'ordine in cui le cose vengono chiamati e l'ordine in cui le cose sono collegate -- ma più spesso avrete strani errori circa i simboli non definiti, che è esattamente ciò che sta accadendo qui.

Basta spostare le definizioni di Rational(const RubyObject&) e Complex(const RubyObject&) nelle rispettive intestazioni e tutto dovrebbe funzionare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top