A cosa serve un riferimento debole senza azzeramento?

4

Quando leggiamo le varie opzioni per lavorare con cose come ARC / GC, spesso mi imbatto in parole esplicite su quali riferimenti deboli stanno azzerando (cioè, il tuo riferimento diventa nil / null / 0 quando l'oggetto è raccolto) e quale non -zeroing (si ottiene un puntatore pendente). Questo mi porta a chiedere: quale possibile uso potrebbe esserci per un puntatore debole senza azzeramento? Non puoi usarlo per niente se non sei sicuro che sia un bene, puoi? E come verificherebbe la sua validità senza rischiare un core dump / segfault?

Addendum: Capisco che siano utili negli ambienti conteggiati di riferimento, e potresti volere usarli quando scrivi il codice della libreria che può essere usato al suo interno, ma non riesco a vederne una buona ragione abbastanza intelligente Collettore ARC-alike o riposizionante. A che serve un riferimento su cui non si può fare affidamento?

    
posta Sophistifunk 17.02.2014 - 23:59
fonte

3 risposte

5

I riferimenti deboli sono importanti nel contesto di uno schema di gestione della memoria con conteggio dei riferimenti. Ad esempio, potremmo avere una struttura dati ad albero in cui ciascun nodo conosce il nodo genitore. Il risultato è una struttura di dati circolare. Quando abbandoniamo tutti i riferimenti noti alla radice dell'albero, l'albero non viene liberato perché i riferimenti dai nodi figlio ai nodi radice impediscono al refcount di cadere a zero.

Questo può essere evitato con riferimenti deboli. Quando ogni riferimento da un figlio al suo genitore è un riferimento debole (un riferimento che non influenza il conteggio dei riferimenti), quindi un riferimento da una delle nostre variabili alla radice dell'albero è il conteggio solo riferimento. Se rimuoviamo quel riferimento, il Refcount raggiunge zero (o no, se sono stati fatti altri riferimenti) e la memoria può essere recuperata.

L'implicazione qui è che finché siamo interessati ai nodi dell'albero, manterremo anche la radice dell'albero stesso. Pertanto, i riferimenti deboli a un nodo genitore rimarranno sempre validi.

Un esempio interessante di un albero con tali proprietà è il Document Object Model per i documenti XML o HTML. Un nodo nel DOM non può esistere separatamente dal documento (o frammento del documento) a cui appartiene. Il DOM contiene accessors che consentono a un'implementazione di mantenere l'integrità referenziale anche se implementata con riferimenti o puntatori deboli.

Ci sono alcune osservazioni importanti.

  • I riferimenti deboli sono in gran parte non necessari con schemi di gestione della memoria più sofisticati come la garbage collection. Ad esempio, potremmo interrompere l'esecuzione di un programma e nel grafico di tutti i riferimenti trovare tutti i sottografi scollegati. Tutti questi sottografi scollegati tranne quello principale possono essere raccolti (anche se l'implementazione della semantica della distruzione può essere difficile, inoltre, questo rende l'idioma RAII impossibile o difficile).

    Come sottolineato nei commenti, alcune implementazioni di notificatori possono trarre grandi benefici dai riferimenti deboli (azzerati) anche nel contesto delle lingue di GC.

  • I riferimenti deboli sono fondamentalmente equivalenti ai normali puntatori. Devi strutturare il tuo programma in modo da garantire che punti sempre a qualcosa di valido. Anche se a volte difficile, l'esperienza ha dimostrato che questo non è esattamente impossibile (ad esempio mantenendo il contesto intorno).

  • Un'implementazione che imposta riferimenti deboli a null quando l'oggetto di riferimento viene liberato può essere altamente inefficiente, poiché abbiamo bisogno di un riferimento dall'oggetto di riferimento per tornare al riferimento stesso, in modo che possa essere ripristinato alla liberazione.

    L'altra opzione sarebbe accedere a ciascun oggetto solo attraverso un proxy, dove i riferimenti deboli aumentano solo il numero di proxy e i riferimenti normali aumentano sia il numero di proxy che l'oggetto reale. Quando il conteggio dell'oggetto interno è zero, il proxy deve essere informato della distruzione per impostare il suo puntatore interno su null . Ciò implica che un riferimento debole di questo design richiede una profonda integrazione con la gestione della memoria del runtime e non può essere aggiunto in seguito come libreria. Questo è più efficiente in termini di memoria, a scapito dell'aggiunta di un livello di puntatore aggiuntivo a ciascun accesso.

risposta data 18.02.2014 - 00:23
fonte
1

Hai ragione - NON dovresti usare riferimenti deboli senza azzeramento. È possibile che si verifichi un codice antico che non utilizza il conteggio automatico dei riferimenti e qualsiasi riferimento in tale codice si comporta in modo efficace come se fosse un riferimento debole senza azzeramento. Quindi, se si utilizza direttamente un codice così antico, questo modello riproduce correttamente il comportamento antico (e indesiderato).

potresti usare un riferimento debole senza azzeramento se l'efficienza è più importante della sicurezza. (Non dire che sia una buona idea, ma quella sarebbe la ragione). È ragionevolmente accettabile se A ha un strong riferimento a B e nient'altro ha, e B ha un riferimento debole ad A, quindi sai che quando il riferimento debole diventa non valido, l'oggetto B che contiene il riferimento debole si allontana comunque. Ma deve essere fatto con attenzione, e personalmente vorrei che significativo guadagni in efficienza prima di considerarlo.

    
risposta data 26.02.2017 - 15:32
fonte
1

In Objective-C, i riferimenti deboli senza zero esistono principalmente per ragioni di compatibilità. Quando si esegue il codice ARC su iOS 4, viene utilizzato un runtime chiamato ARC-lite che supporta la maggior parte dell'ARC ad eccezione dell'azzeramento dei riferimenti deboli.

Se imposti il tuo progetto su iOS 4, Xcode rifiuterà di compilare il codice che utilizza la parola chiave weak .

Anche Apple raccomanda esplicitamente unsafe_unretained anziché weak quando si lavora con determinate classi, ancora per ragioni di compatibilità con codice precedente.

C'è anche un piccolo costo in termini di prestazioni per accedere a riferimenti deboli, sebbene per la maggior parte degli scopi questo sia trascurabile.

    
risposta data 18.02.2014 - 00:41
fonte

Leggi altre domande sui tag