2009-05-24 15 views
8

Il nostro team ha utilizzato Delphi 6 per molti anni, quindi è passato a Delphi 2006 anni fa. Con entrambe le versioni abbiamo il seguente problema: frequentemente il compilatore si lamenta di un'unità che è presumibilmente utilizzata in modo ricorsivo. Questa unità è un'unità LOC 40k che è al centro di un progetto con quasi 1 milione di LOC (terza parte inclusa).Errore di riferimento circolare errato

Il messaggio di errore non è corretto: una compilazione completa sul progetto funziona sempre. Sfortunatamente, il messaggio di errore non ci dice dove si trova il presunto riferimento circolare, solo il nome di quell'unità. A volte capita anche che i messaggi di errore validi siano elencati da 2 a 4 volte finché il problema di riferimento circolare non viene "trovato". Chiaramente il compilatore è in esecuzione in un cerchio qui. A causa delle dimensioni di tale progetto è difficile trovare il problema manualmente. Perciò ho creato uno strumento che dimostra che non esiste realmente un riferimento circolare (lo strumento crea un grafico di dipendenza orientato delle unità e determina i componenti di coerenza in quel grafico - non ce ne sono nessuno eccetto se li inserisco deliberatamente).

Questo non riguarda solo la compilazione F9 ma anche il completamento/approfondimento del codice che non funziona la maggior parte del tempo. A volte funziona quando premo ctrl-space una seconda volta ...

Qualche idea su come possiamo isolare o addirittura risolvere il problema? Si noti che sarà molto difficile suddividere l'unità LOC 40k in unità più piccole perché contiene circa 15 classi di grandi dimensioni che dipendono l'una dall'altra nella sezione dell'interfaccia (so che è male ma dovrebbe funzionare comunque).

Aggiornamento
Siamo costantemente refactoring, ma questo è un'unità difficile da refactoring perché tutto dipende da tutto, o quasi. Abbiamo cercato di aggirarlo tramite le interfacce ma stiamo parlando di alcune classi con 100 di metodi e proprietà. E sarebbe più lento.

L'aggiornamento a D2009 può essere un'opzione in fondo alla strada, ma al momento siamo bloccati con D2006 (la roba unicode e il cartellino del prezzo sono due dei tappi qui). La domanda è comunque se potesse essere d'aiuto dato che il problema è lì fin dal D6 almeno.

Informazioni sul ritaglio delle clausole di utilizzo, lo abbiamo fatto frequentemente con Icarus. Ma questo non ha aiutato finora. Ora ci sono fino a 90 unità personalizzate nella sezione interfaccia. Tuttavia, con un riferimento circolare reale, il problema potrebbe essere in qualsiasi unità. Ho anche provato ad aggiungere tutte le unità al dpr.

Il progetto condivide molto codice con altri progetti e alcuni IFDEF. Tuttavia, le definizioni non sono impostate nelle opzioni del progetto ma tramite un file di inclusione comune. Pertanto tutti i moduli dovrebbero vedere le stesse definizioni. Inoltre, il problema si ripresenta poco dopo una ricostruzione completa senza passare a un altro progetto.

risposta

0

Avete altri progetti che utilizzano parte della stessa base di codici? Se si compila uno di essi con diverse impostazioni del compilatore o IFDEF, potrebbe cambiare alcune cose in alcune DCU che comporterebbero una dipendenza circolare. Una ricostruzione completa ricostruisce tutte le DCU e quindi il problema scompare.

0

Provare Icarus (gratuito) da Peganza. Se questo non ti dice quale sia il problema, prova il loro Pascal Analyzer.

2

Sembra chiaro che questo è dovuto a una leggera differenza tra il compilatore di sfondo e la cosa reale. Potresti dare un'occhiata (QualityCentral) a ciò che è noto su quell'argomento.

Inoltre, poiché non è stato esplicitamente indicato, è necessario rimuovere le unità non necessarie e spostare le istruzioni degli usi fino all'implementazione, se possibile. Forse il tuo strumento potrebbe aiutarti.

E per sicurezza, è necessario controllare gli alias dell'unità e le impostazioni del percorso.

4

Probabilmente sarà downvoted per questo. In D2005 avevo un'unità di localizzazione 10k (datamodule) che flat out interrompeva la compilazione. Doveva separare alcuni dataset/codice in un altro datamodule. Quell'unità da 10k era ed è un casino. Dovresti davvero prendere in considerazione la possibilità di rielaborare un codice per altre unità. Il mio modulo ha visto D2005/separazione ulteriormente peggiorata, ma è ancora compilato in D2007. Quindi la mia risposta è a) refactor e b) upgrade a D2009.

2

Si scrive che una compilazione completa ha sempre esito positivo, ma poco dopo la build incrementale fallisce con questo errore. Supponendo che questo si verifichi nell'IDE, hai provato a utilizzare il compilatore di riga di comando dcc32 per creare build incrementali?

Se non si alimenta l'opzione "-Q" (che probabilmente la maggior parte dei Makefile o degli script per le build da riga di comando fa) genererà un sacco di informazioni su quali file compila in quale ordine. Potresti provare a fare una build incrementale dopo che l'errore è apparso nell'IDE, oppure puoi tenere una riga di comando aperta accanto all'IDE e Alt + Tab ad essa per la compilazione, saltando completamente la compilazione nell'IDE.

Suppongo semplicemente che tu abbia un modo per creare utilizzando dcc32, in un modo o nell'altro: con le dimensioni del tuo progetto non riesco a immaginare diversamente.

+0

Destro, usiamo dcc32 in uno script di compilazione completo su tutti i progetti (e altro ancora). Non vedo l'ora di usarlo come sostituto per la compilazione di IDE; non sarebbe d'aiuto con l'intuizione del codice e chissà quante volte sarebbe necessario. Ma forse è un modo per diagnosticare il problema? Idealmente, dcc32 incremental si imbatterebbe nello stesso problema e il suo output innesca alcune idee ... –

+0

Sì, questo è esattamente quello che stavo cercando di suggerire, forse non ci sono riuscito a chiarire però :-(Scusa, usando dcc32 dovresti vedi quali file sono compilati più volte, e dopo di che il file si ferma. A meno che il compilatore IDE e il dcc32 siano davvero così diversi, ma questo non lo assumerei – mghie

2

Cadiamo regolarmente in problemi simili e non siamo mai riusciti (o infastiditi abbastanza a lungo) a trovare la causa precisa. Sembra esserci un problema nell'ordine che Delphi sceglie di compilare le unità quando si preme Ctrl-F9, che è incompatibile con l'ordine di dipendenza effettivo delle unità.

  • Hai provato a eliminare "MyBigFatUnit.dcu" prima di premere Ctrl-F9?
  • Hai provato a riordinare la dichiarazione delle unità nei file dpr/dpk, in modo che le unità vengano visualizzate in un ordine di compilazione corretto? (vale a dire se l'unità B dipende dall'unità A, l'unità A dovrebbe apparire prima in dpr/dpk)
0

Abbiamo anche questo problema, anche con una base di codice abbastanza grande.

Attualmente stiamo utilizzando D2009, ma abbiamo riscontrato questo problema con tutte le versioni precedenti di Delphi.

Si verifica più frequentemente subito dopo aver eseguito un aggiornamento dal controllo del codice sorgente, quindi sospetto che ci sia qualche problema di timestamp all'interno del processo di compilazione di Delphi.

Nel nostro caso, se Ctrl-F9 non riesce e riporta il riferimento circolare, un secondo Ctrl + F9 generalmente funzionerà

0

Un modo in cui mi è stato detto per affrontare questo è quello di aprire un altro file arbitrari nel progetto , cambia il file, salvalo e prova a eseguire di nuovo la compilazione incrementale. Sorprendentemente, questo di solito funziona.

Abbiamo un progetto di 4 MLOC in cui questo viene saltuariamente e questa "soluzione" funziona per me.

0

Ho combattuto prima, nella mia esperienza l'errore è quasi legittimo.È passato un po 'di tempo (l'errore non ha nulla a che fare con la versione), ma la mia memoria della situazione è che coinvolge un ciclo in cui parte del ciclo è in fase di implementazione.

L'unità A utilizza B nell'implementazione. L'unità B utilizza A nell'interfaccia. Se si compila B, prima chiama A, ma poiché la chiamata per B è in esecuzione, ha successo. Se si compila A per primo si chiama B, B si gira e chiama A nell'interfaccia, boom. Tali loop sono sicuri solo se entrambi i riferimenti incrociati sono in fase di implementazione.

La soluzione è progettare le cose in modo che ci sia un minimo di materiale utilizzato nell'interfaccia e assicurarsi che non ci sia nulla di simile a un loop in quelle unità. Fintanto che mantieni le tue definizioni di tipo separate dalle unità con codice, questo è abbastanza facile da fare.

L'errore che va e viene in base a ciò che si sta facendo è un segno distintivo di questo problema in quanto si tratta di come si entra nel ciclo. Quando esegui una compilazione completa, l'ordine è coerente e puoi ottenerlo al 100% o allo 0%, non è casuale.

+0

Loren, capisco il tuo punto - ma quello che descrivi è perfettamente codice valido e dovrebbe funzionare.E 'documentato in questo modo.Un compilatore che lavora la maggior parte del tempo è ancora un compilatore rotto, giusto? FWIW, una volta ho provato a spostare la maggior parte degli "usi" dall'interfaccia all'implementazione. ricorda quante unità sono rimaste nell'interfaccia ma ricordo che non è stato di aiuto, è frustrante, perché questo messaggio di errore non elenca il riferimento circolare esatto? Specialmente ora quando il cerchio presunto è un codice valido, potrebbe aiutare un ton per imparare esattamente cosa doveva essere cambiato. –

+0

@deepc: sono d'accordo che dovrebbe funzionare. È passato così tanto tempo da quando l'ho visto che non ricordo il testo, non fornisce il nome dell'unità che lo ha fatto saltare in aria? Ho anche trovato utile il compilatore a riga di comando per capirlo - reindirizzare l'output in un file in modo da poter vedere effettivamente quali file ha compilato, non solo su cosa sta lavorando ora. Se mantieni i tuoi tipi separati dal tuo codice è praticamente un non-problema, a meno che il tuo layout non sia quello degli spaghetti. –

Problemi correlati