43 votes

Comment fonctionne l'attribution de l'object_id ?

Je m'amuse avec la méthode de Ruby. .object_id et j'ai remarqué que, dans plusieurs sessions successives d'irb, j'obtiens ces résultats identiques :

false.object_id // 0
true.object_id // 2
nil.object_id // 4
100.object_id // 201

En fait, l'objet_id de chaque entier semble être ((valeur * 2) + 1).

D'autre part, l'object_id d'une chaîne donnée n'est jamais le même après avoir quitté et relancé irb.

Cela soulève plusieurs questions pour moi :

  1. Y a-t-il un système connu par lequel certains object_id sont déterminés ? Les autres sont-elles fondamentalement aléatoires ?
  2. Les identifiants de true, false et nil ne sont pas séquentiels. Existe-t-il un moyen de demander quel objet est représenté par un identifiant donné ? (Je suis curieux de savoir à quoi sont liés les autres ids à un chiffre).
  3. Pourriez-vous (non pas que vous devriez) écrire du Ruby obscurci où vous utilisez des identifiants d'objets connus pour faire référence à des objets sans les nommer, comme "objet d'id 201 + objet d'id 19" pour signifier "100 + 9" ?

Mise à jour

En utilisant la suggestion d'Andrew Grimm, j'ai essayé de découvrir d'autres objets "low id", mais je n'ai rien trouvé :

  • Il ne semble pas y avoir d'autres objets à numérotation paire dans cette séquence - les identifiants 6, 8, 10, etc. ne correspondent à rien.
  • Comme le laissait entendre mon expérience précédente, tous les identifiants impairs appartiennent à des numéros. Plus précisément, l'identifiant 1 correspond au nombre 0, le 3 au 1, le 5 au 2, et ainsi de suite.

63voto

sepp2k Points 157757

En IRM, le object_id d'un objet est la même que la VALUE qui représente l'objet au niveau C. Pour la plupart des types d'objets, ce VALUE est un pointeur vers un emplacement en mémoire où les données réelles de l'objet sont stockées. Évidemment, cet emplacement sera différent au cours de plusieurs exécutions, car il dépend uniquement de l'endroit où le système a décidé d'allouer la mémoire, et non d'une quelconque propriété de l'objet lui-même.

Cependant, pour des raisons de performance true , false , nil y Fixnum sont traités de manière particulière. Pour ces objets, il n'y a pas réellement de structure contenant les données de l'objet en mémoire. Toutes les données de l'objet sont codées dans le fichier VALUE lui-même. Comme vous l'avez déjà compris, les valeurs de false , true , nil et tout Fixnum i sont 0 , 2 , 4 y i*2+1 respectivement.

La raison pour laquelle cela fonctionne est que sur tous les systèmes sur lesquels MRI fonctionne, 0 , 2 , 4 y i*2+1 ne sont jamais des adresses valides pour un objet sur le tas, donc il n'y a pas de chevauchement avec les pointeurs vers les données de l'objet.

31voto

Andrew Grimm Points 22996

Affectation d'un nombre entier (value * 2) + 1 et les non-entiers (x * 2) est analogue à Le paradoxe de Hilbert du Grand Hôtel qui décrit comment affecter un nombre infini de clients à un hôtel infini.

En ce qui concerne la recherche d'objets par leur ID, il y a ObjectSpace._id2ref(object_id) . A moins que votre implémentation ne dispose pas d'ObjectSpace.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X