سؤال

مؤخرا عن سلسلة حرفية في. NET اشتعلت عيني. وأنا أعلم أن سلسلة حرفية و داخليا بحيث سلاسل مختلفة مع نفس القيمة تشير إلى نفس الكائن . وأعلم أيضا أن سلسلة يمكن يعتقل في وقت التشغيل:

string now = DateTime.Now.ToString().Intern(); 

ومن الواضح أن السلسلة التي تم اعتقالهم في وقت يتواجد على كومة لكن أنا كان يفترض أن يتم وضع حرفي في مقطع البيانات للبرنامج (وقالت حتى في بلدي <لأ href = "https://stackoverflow.com/questions/ 372354 / سلسلة ثبات # 372380 "> الجواب لوقالت السؤال). ومع ذلك أنا لا أتذكر رؤية هذا في أي مكان. افترض أن هذا هو الحال منذ ذلك كيف لي أن تفعل ذلك، وحقيقة أن يتم استخدام IL تعليمات ldstr للحصول على الحرفية ويبدو أن لا تخصيص عقده يبدو لدعم لي.

لخفض قصة قصيرة طويلة، حيث لا يقيم سلسلة حرفية؟ هو على كومة، مقطع البيانات أو بعض مكان أنا لم أفكر في؟


تعديل: إذا سلسلة حرفية <م> لا الموجودة على كومة، وعندما هم المخصصة؟

هل كانت مفيدة؟

المحلول

وسلاسل في. NET هي أنواع المراجع، لذلك هم دائما على كومة (حتى عندما يتم اعتقالهم هم). يمكنك التحقق من ذلك باستخدام المصحح مثل WinDbg.

إذا كان لديك الطبقة أدناه

   class SomeType {
      public void Foo() {
         string s = "hello world";
         Console.WriteLine(s);
         Console.WriteLine("press enter");
         Console.ReadLine();
      }
   }

واستدعاء Foo() على سبيل المثال، يمكنك استخدام WinDbg لتفقد الكومة.

وعلى الأرجح أن يتم تخزين مرجع في السجل للبرنامج صغير، وبالتالي فإن الأسهل هو أن تجد الإشارة إلى سلسلة محددة هي عن طريق القيام !dso. وهذا يعطينا عنوان سلسلة لدينا في السؤال التالي:

0:000> !dso
OS Thread Id: 0x1660 (0)
ESP/REG  Object   Name
002bf0a4 025d4bf8 Microsoft.Win32.SafeHandles.SafeFileHandle
002bf0b4 025d4bf8 Microsoft.Win32.SafeHandles.SafeFileHandle
002bf0e8 025d4e5c System.Byte[]
002bf0ec 025d4c0c System.IO.__ConsoleStream
002bf110 025d4c3c System.IO.StreamReader
002bf114 025d4c3c System.IO.StreamReader
002bf12c 025d5180 System.IO.TextReader+SyncTextReader
002bf130 025d4c3c System.IO.StreamReader
002bf140 025d5180 System.IO.TextReader+SyncTextReader
002bf14c 025d5180 System.IO.TextReader+SyncTextReader
002bf15c 025d2d04 System.String    hello world             // THIS IS THE ONE
002bf224 025d2ccc System.Object[]    (System.String[])
002bf3d0 025d2ccc System.Object[]    (System.String[])
002bf3f8 025d2ccc System.Object[]    (System.String[])

والآن استخدام !gcgen لمعرفة أي جيل المثال في:

0:000> !gcgen 025d2d04 
Gen 0

وانها في الجيل الصفر - أي قد يكون مجرد تخصيص ذلك. من الذي تأصيل ذلك؟

0:000> !gcroot 025d2d04 
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 1660
ESP:2bf15c:Root:025d2d04(System.String)
Scan Thread 2 OSTHread 16b4
DOMAIN(000E4840):HANDLE(Pinned):6513f4:Root:035d2020(System.Object[])->
025d2d04(System.String)

ووESP هو كومة لطريقة Foo() لدينا، ولكن لاحظ أن لدينا object[] كذلك. هذا هو الجدول المتدرب. دعونا نلقي نظرة.

0:000> !dumparray 035d2020
Name: System.Object[]
MethodTable: 006984c4
EEClass: 00698444
Size: 528(0x210) bytes
Array: Rank 1, Number of elements 128, Type CLASS
Element Methodtable: 00696d3c
[0] 025d1360
[1] 025d137c
[2] 025d139c
[3] 025d13b0
[4] 025d13d0
[5] 025d1400
[6] 025d1424
...
[36] 025d2d04  // THIS IS OUR STRING
...
[126] null
[127] null

وأنا خفض الانتاج الى حد ما، ولكن تحصل على هذه الفكرة.

في ختام : لالسلاسل على كومة - حتى عندما يتم اعتقالهم هم. يحمل الجدول المعتقلين إشارة إلى المثيل على الكومة. بمعنى آخر. لا يتم جمع السلاسل داخليا خلال GC لأن جذور الجدول المعتقلين منهم.

نصائح أخرى

في جاوة (من جافا مسرد ):

<اقتباس فقرة>   

في JVM الشمس، يتم تخزين سلاسل داخليا (والذي يتضمن سلسلة حرفية) في تجمع خاص من ذاكرة الوصول العشوائي يسمى بيرم جنرال، حيث يحمل JVM أيضا الطبقات ومخازن تجميع أصلا التعليمات البرمجية. ومع ذلك، فإن سلاسل intered تتصرف بشكل لا يختلف عما كان أنها تم تخزينها في كومة كائن العادية.

وتصحيح لي إذا كنت مخطئا ولكن لا كافة الكائنات الموجودة على كومة، في كل من جافا و. NET؟

في صافي، يتم تخزين سلسلة حرفية عند "داخليا"، في بنية بيانات خاص يسمى، "الجدول المتدرب". هذا هو منفصل عن كومة والمكدس. لم يتم اعتقالهم كافة السلاسل ولكن ... أنا متأكد أن تلك التي لا يتم تخزينها على الكومة.

ولا يعرفون جافا

ولقد وجدت هذا في الموقع MSDN حول في ldstr IL تعليمات :

<اقتباس فقرة>   

والتعليمة ldstr يدفع مرجع كائن (نوع O) إلى كائن سلسلة جديدة يمثل سلسلة معينة حرفية المخزنة في البيانات الوصفية. تعليمات ldstr على تخصص الكمية المطلوبة من الذاكرة و ينفذ أي تحويل الشكل المطلوب لتحويل سلسلة حرفية من النموذج المستخدم في الملف إلى تنسيق سلسلة المطلوبة في وقت التشغيل.

     

ووسي إل أي (CLI) تضمن أن نتيجة لاثنين تعليمات ldstr اشارة الى اثنين من الرموز الفوقية التي لها نفس تسلسل الأحرف تعود بالضبط الكائن سلسلة نفسه (وهي عملية تعرف باسم "سلسلة interning").

وهذا يعني أن سلسلة حرفية وفي الواقع تخزينها على الكومة في. NET (على عكس جافا ك <لأ href = "https://stackoverflow.com/questions/372547/where-do-java-and-net- وأشار سلسلة حرفية-يقيم # 372610 "> من بواسطة mmyers ).

في جاوة، سلاسل مثل كل الكائنات الموجودة في الكومة. فقط المتغيرات المحلية البدائية ([إينتس]، حرف ويشير إلى الكائنات) يقيمون في كومة.

والمعتقلين في سلسلة في جافا تقع في بركة منفصلة تسمى بركة سلسلة. يتم الحفاظ على هذا التجمع من قبل الطبقة سلسلة ويقيم على كومة العادية (وليس تجمع بيرم على النحو المذكور أعلاه، الذي يستخدم لتخزين البيانات الفئة).

وكما أفهم لم يتم اعتقالهم جميع سلاسل، ولكن الدعوة myString.intern () بإرجاع سلسلة التي يتم ضمان من بركة سلسلة.

وانظر أيضا: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally. أتش تي أم أل وجافادوك HTTP: // جافا. sun.com/j2se/1.5.0/docs/api/java/lang/String.html#intern ()

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top