70 votes

Chaîne corrompue en C #

Je suis tombé sur "CorruptedString" (la Solution). Voici un code de programme à partir du livre de:

var s = "Hello";
string.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 d'affichage "aaaaa"? Je comprends ce programme comme suit:

  1. Le CLR réserves "bonjour" dans la stagiaire de la piscine (j'ai l'image de la stagiaire de la piscine comme un ensemble de chaînes de caractères).
  2. string.Intern(s) ne fait rien, parce que le CLR avait réservé chaîne "Hello" qu'il renvoie l'adresse de l'réservés chaîne "Hello" (objet a la même adresse)
  3. Le programme modifie le contenu de la chaîne "Hello" par l'intermédiaire d'un pointeur
  4. ??? Le Bonjour de la chaîne devrait être absent dans la stagiaire de la piscine, et il convient d'erreur! Mais c'est OK; le programme s'exécute correctement.

Comme je comprends le stagiaire de la piscine, c'est comme une sorte de dictionnaire de chaîne en chaîne. Ou peut-être que j'ai raté quelque chose?

65voto

Jaroslav Kadlec Points 2021

Lorsque vous utilisez "Bonjour" pour la première fois, il est interné dans la demande mondiale de stocker des chaînes de caractères. Basé sur le fait que vous êtes d'exécution en unsafe mode ( unsafe ici) vous obtenez une référence directe à des données stockées dans les emplacements d'origine allouée à la valeur de chaîne de caractères s, par

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

vous êtes l'édition de ce mémoire. Lorsqu'il accède à la boutique de l'internement des chaînes à la prochaine fois, il va utiliser la même adresse mémoire, contenant les données que vous avez simplement changé. Ce ne serait pas possible sans l' unsafe. string.Intern(s); ne joue pas ici un rôle; il se comporte de la même si vous en commentaire.

Puis par

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

.NET regarde si il y a une entrée pour une adresse obtenue pour "Hello" et il est: celui qui vous avez juste mis à jour pour être "aaaaa". Le nombre d' 'a' caractères est déterminée par la longueur de l' "Hello".

5voto

Sid Points 5659

Même si @Jaroslav Kadlec réponse est correcte et complète, je voudrais ajouter quelques informations supplémentaires sur le comportement du code et pourquoi string.Intern(s); est inutile dans ce cas.

À Propos De Stagiaire De La Piscine

En fait .NET exécuter automatiquement chaîne de stage pour tous les littéraux de chaîne, cela se fait à l'aide d'une table qui stocke les références à toutes les chaînes uniques dans notre application.

Cependant, il est important de noter que seuls explicitement déclaré chaîne sont internés sur la compilation de scène.

Considérons 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 stagiaire une chaîne de caractères au moment de l'exécution, ce qui peut être fait par String.Intern après vérification avec String.IsInterned.

Afin de revenir à l'extrait de l'OP:

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

Dans ce cas - string.Intern(s); est inutile car il est déjà internés lors de la compilation de la scène.

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