Chaîne corrompue en C #

Je suis tombé sur “CorruptedSsortingng” (Solution) . Voici le code du programme suivant du livre:

var s = "Hello"; ssortingng.Intern(s); unsafe { fixed (char* c = s) for (int i = 0; i < s.Length; i++) c[i] = 'a'; } Console.WriteLine("Hello"); // Displays: "aaaaa" 

Pourquoi ce programme affiche “aaaaa”? Je comprends ce programme comme suit:

  1. Le CLR réserve “bonjour” dans le pool interne (j’imagine le pool interne sous la forme d’un ensemble de chaînes).
  2. ssortingng.Intern(s) ne fait en réalité rien, car le CLR avait réservé la chaîne “Hello” – il ne fait que renvoyer l’adresse de la chaîne “Hello” réservée (l’object a la même adresse)
  3. Le programme modifie le contenu de la chaîne “Hello” via un pointeur
  4. ??? La chaîne Hello devrait être absente du pool interne, et cela devrait être une erreur! Mais c’est OK; le programme s’exécute avec succès.

Comme je comprends le pool interne, c’est comme une sorte de dictionnaire de chaîne à chaîne. Ou peut-être que j’ai raté quelque chose?

Lorsque vous utilisez “Hello” pour la première fois, il est interné dans le magasin global de chaînes de l’application. Basé sur le fait que vous exécutez en mode unsafe (plus unsafe ici ), vous obtenez une référence directe aux données stockées dans les emplacements alloués à l’origine pour la valeur de chaîne s , donc par

 for (int i = 0; i < s.Length; i++) c[i] = 'a'; 

vous modifiez ce qui est en mémoire. Lorsqu'il accédera au magasin de chaînes internes la prochaine fois, il utilisera la même adresse en mémoire, contenant les données que vous venez de modifier. Cela ne serait pas possible sans unsafe . ssortingng.Intern(s); ne joue pas de rôle ici; il se comporte de la même manière si vous le commentez.

Puis par

 Console.WriteLine("Hello"); // Displays: "aaaaa" 

.NET vérifie s'il y a une entrée pour une adresse obtenue pour "Hello" et il y a: celle que vous venez de mettre à jour pour être "aaaaa" . Le nombre de caractères 'a' est déterminé par la longueur de "Hello" .

Bien que la réponse de @Jaroslav Kadlec soit correcte et complète, je voudrais append quelques informations supplémentaires sur le comportement du code et pourquoi ssortingng.Intern(s); est inutile dans ce cas .

À propos du pool de stagiaires

En fait, .NET exécute automatiquement l’internalisation de chaînes pour tous les littéraux de chaîne, en utilisant une table spéciale qui stocke les références à toutes les chaînes uniques de notre application.

Cependant, il est important de noter que seules les chaînes explicitement déclarées sont internées sur la compilation .

Considérez le code suivant:

 var first = "Hello"; //Will be interned var second = "World"; //Will be interned var third = first + second; //Will not be interned 

Bien sûr, dans certaines circonstances, nous aimerions interner une chaîne au moment de l’exécution et cela peut être fait par Ssortingng.Intern après avoir vérifié avec Ssortingng.IsInterned .

Revenons donc à l’extrait de l’OP:

 //... var s = "Hello"; ssortingng.Intern(s); //... 

Dans ce cas, ssortingng.Intern(s); est inutile car il est déjà interné à la compilation.