Come sono organizzati in memoria gli "oggetti" e le "classi" OOP in termini di linguaggio assembly?


13

Come sono organizzati gli oggetti nella memoria?

Ad esempio, so che una funzione è un pezzo di codice in memoria, che prevede parametri tramite lo stack e / o i registri e gestisce il proprio frame dello stack.

Ma gli oggetti sono una struttura molto più complicata. Come sono organizzati? Ogni oggetto ha "collegamenti" ai metodi e passa l'indirizzo a se stesso a quel metodo?

Sarebbe bello vedere una buona spiegazione di questo argomento.

UPD. Ho reso la domanda più esatta e sono principalmente interessato alle lingue di battitura statica.


4
Può variare selvaggiamente tra lingue diverse, specialmente tra lingue tipizzate dinamicamente e staticamente. Puoi restringere la tua domanda alle lingue OO che ti interessano di più?
Bart van Ingen Schenau,

Ho aggiornato la domanda, quindi penso che le lingue tipizzate in modo dinamico siano più difficili da capire.
Nikolai Golub,

Risposte:


17

Se non esiste un dispacciamento dinamico (polimorfismo), i "metodi" sono solo funzioni zuccherine, forse con un parametro implicito aggiuntivo. Di conseguenza, le istanze di classi senza comportamento polimorfico sono essenzialmente C structai fini della generazione del codice.

Per l'invio dinamico classico in un sistema di tipo statico, esiste sostanzialmente una strategia predominante: vtables. Ogni istanza ottiene un puntatore aggiuntivo che fa riferimento a (una rappresentazione limitata di) il suo tipo, soprattutto la vtable: un array di puntatori a funzione, uno per metodo. Poiché l'intero set di metodi per ogni tipo (nella catena di ereditarietà) è noto al momento della compilazione, è possibile assegnare indici consecutivi (0..N per N metodi) ai metodi e richiamare i metodi cercando il puntatore a funzione in la vtable usando questo indice (passando nuovamente il riferimento all'istanza come parametro aggiuntivo).

Per linguaggi più dinamici basati su classi, in genere le classi stesse sono oggetti di prima classe e ogni oggetto ha invece un riferimento al suo oggetto classe. L'oggetto classe, a sua volta, possiede i metodi in qualche modo dipendente dalla lingua (in Ruby, i metodi sono una parte fondamentale del modello a oggetti, in Python sono solo oggetti funzione con piccoli involucri attorno a loro). Le classi in genere memorizzano anche i riferimenti alle loro superclassi e delegano la ricerca di metodi ereditati a tali classi per facilitare la metaprogrammazione che aggiunge e modifica i metodi.

Esistono molti altri sistemi che non si basano sulle classi, ma differiscono in modo significativo, quindi selezionerò solo un'interessante alternativa di progettazione: quando puoi aggiungere nuovi (set di) metodi a tutti i tipi a piacimento nel programma ( ad es. classi di tipi in Haskell e tratti in Rust), non è noto l'intero set di metodi durante la compilazione. Per risolvere questo, si crea una vtable per tratto e li passa in giro quando è richiesta l'implementazione del tratto. Cioè, codice come questo:

void needs_a_trait(SomeTrait &x) { x.method2(1); }
ConcreteType x = ...;
needs_a_trait(x);

è compilato in questo modo:

functionpointer SomeTrait_ConcreteType_vtable[] = { &method1, &method2, ... };
void needs_a_trait(void *x, functionpointer vtable[]) { vtable[1](x, 1); }
ConcreteType x = ...;
needs_a_trait(x, SomeTrait_ConcreteType_vtable);

Questo significa anche che le informazioni sulla vtable non sono incorporate nell'oggetto. Se desideri riferimenti a una "istanza di un tratto" che si comporterà correttamente quando, ad esempio, è archiviato in strutture di dati che contengono molti tipi diversi, puoi creare un puntatore grasso (instance_pointer, trait_vtable) . Questa è in realtà una generalizzazione della strategia di cui sopra.


5

Questa è la risposta nel senso del proverbio "se dai a un uomo un pesce gli dai da mangiare per un giorno, mentre se gli insegni a pescare gli dai da mangiare per tutta la vita" poiché la tua domanda è molto ampia

1. ricerca fonti di informazione aperte

Google per "programmazione orientata agli oggetti assembly" elenca molte diverse risorse pertinenti.

ad es. Programmazione orientata agli oggetti in assemblea, Ethan J. Eldridge, il 15 dicembre 2011 è arrivato come terzo collegamento e sembra buono

2. imparare dal codice scritto a mano esistente

Puoi vedere come funziona studiando i codici sorgente scritti con alcuni linguaggi assembly popolari con OOP esplicitamente dichiarato ad es

3. apprendere da schemi di codice generati dai compilatori

Puoi vedere come funziona studiando i file di linguaggio assembly intermedio prodotti dai compilatori OOP di tua scelta. Entrambi i compilatori C ++ e FreePascal possono essere configurati in modo da poter vedere come appare la trascrizione del codice OOP di alto livello nel codice del linguaggio assembly

4. risolvi il puzzle con il tuo buon senso

Adesso è troppo tardi perché conosci già i suggerimenti di altre risposte. Ma prima che Internet fosse così facile da cercare e prima che ci fossero siti in cui puoi ottenere la tua risposta senza sforzo entro qualche ora gratuitamente da alcuni volontari che l'hanno appresa a fatica, l'unico metodo di lavoro disponibile gratuitamente per chiunque era

Chiediti: "come lo implementerei?"

Molto spesso dopo diversi giorni di esecuzione del processo di riflessione sullo sfondo e dopo aver gettato via diversi progetti di bozze di carta, scopriresti che la soluzione che hai trovato è molto simile alla soluzione che altri programmatori hanno inventato e già implementato


Ora la mia risposta è basata sull'opinione, non risponde direttamente alla domanda di OP e gli utenti senior ad alta reputazione possono liberamente sottovalutarmi

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.