Ho scritto un set di componenti che si collegano tra loro tramite le proprietà dell'interfaccia pubblicate. Sono registrati e installati in un pacchetto di progettazione.Bug e soluzioni alternative all'interfaccia pubblicate
Utilizzare le proprietà di interfaccia pubblicate non è così comune in Delphi e, quindi, non sorprende che non funzioni altrettanto bene.
Funziona correttamente quando i componenti si trovano sullo stesso modulo, tuttavia i collegamenti delle proprietà dell'interfaccia tra componenti su moduli diversi causano problemi.
A differenza dei collegamenti oggetto ai componenti su un altro modulo, i collegamenti di interfaccia non sembrano essere riconosciuti da IDE. Quello che intendo è meglio descritto da un esempio, quando hai 2 moduli aperti in IDE e hai collegamenti tra i componenti su di essi, quindi provando a passare alla visualizzazione modulo come testo (Alt + F12) farebbe in modo che l'IDE si lamenti correttamente:
Module 'UnitXXX.pas' has open descendents or linked modules. Cannot close.
Ma se la proprietà è un'interfaccia allora questo non accade, ciò che accade invece è che il collegamento è tagliato (e questa è la migliore delle ipotesi quando si utilizza meccanismo di notifica per cancellare i riferimenti, altrimenti sei lasciato con un puntatore non valido)
Un altro problema, probabilmente come conseguenza dello stesso bug, è che quando si apre un progetto in IDE, l'ordine in cui verranno riaperti i moduli d non è definito, quindi IDE può provare ad aprire un modulo che contiene componenti che hanno collegamenti di interfaccia con componenti su un altro modulo, ma quell'altro modulo non viene ancora ricreato. In questo modo si ottengono effettivamente collegamenti AV o interrotti.
Indietro negli anni '90 mentre ho usato Datasets
e Datasources
Ricordo problemi simili con i collegamenti tra le forme che scompaiono, quindi questo è un po 'simile.
Come soluzione temporanea ho aggiunto proprietà pubblicate duplicate, per ogni proprietà di interfaccia ne ho aggiunto un'altra dichiarata come TComponent
. Ciò rende Delphi consapevole del fatto che esiste un collegamento tra le forme, ma a dir poco è una brutta soluzione.
Quindi mi chiedo se c'è qualcosa che posso fare per risolvere questo problema? È un bug IDE e probabilmente non risolvibile direttamente, ma forse posso ignorare qualcosa o altrimenti collegarlo al meccanismo di streaming per risolvere in modo più efficace questo bug.
Non sono mai andato così in profondità nel meccanismo di streaming, ma ho il sospetto che il meccanismo di Fixup debba occuparsi di questo. C'è un csFixups
TComponentState
quindi spero che sia possibile una soluzione.
Modifica: Utilizzo D2007.
Aggiornamento:
new updated esempio riproducibile caricato a http://www.filedropper.com/fixupbugproject2
Aggiunto property ComponentReference: TComponent
in modo che sia facile da confrontare e tracciare l'interfaccia vs Streaming componente.
Ho ristretto il problema a livello di assemblatore che è un po 'fuori dalla mia profondità.
Nel procedimento GlobalFixupReferences
in classes
unità chiama:
(GetOrdProp(FInstance, FPropInfo) <> 0)
che alla fine esegue:
function TInterfacedComponent.GetInterfaceReference: IInterface;
begin
// uncomment the code bellow to avoid exception
{ if (csLoading in ComponentState) and (FInterfaceReference = nil) then
// leave result unassigned to avoid exception
else
}
result := FInterfaceReference; // <----- Exception happens here
end;
Come si può vedere dal commento, l'unico modo che ho trovato per evitare l'eccezione è lasciare il risultato non assegnato, ma ciò interrompe la funzionalità poiché il confronto sopra riportato in GlobalFixupReferences
non riesce a causa di GetOrdProp <> 0
, che interrompe il collegamento .
tracciando più profonda la posizione più precisa eccezione è in
procedure _IntfCopy(var Dest: IInterface; const Source: IInterface);
in system
unità
Questa linea, in particolare, solleva una read of address 0x80000000
{ Now we're into the less common cases. }
@@NilSource:
MOV ECX, [EAX] // get current value
Quindi, perché MOV
fallisce e che cosa c'è di sbagliato con ECX
o EAX
Non ne ho idea.
Questa è una domanda interessante. Sembra un po 'oltre la mia esperienza personale. Ho il sospetto che tu abbia un progetto dimostrativo che possa aiutare qualsiasi investigatore in erba. –
@DavidHeffernan È abbastanza facile da riprodurre, tutto ciò che serve è un discendente di TComponent con una proprietà pubblicata di tipo IInterface. Registrarlo, installare il pacchetto e rilasciarne uno su ciascuno dei due moduli vuoti. Detto questo, potrei farlo io stesso e lasciarti giocare con questo ... –
Penso che sarebbe di grande aiuto se lo facessi. Abbassare le barriere per noi. –