字符串初始化过程中发生的情况

本文关键字:情况 初始化 过程中 字符串 | 更新日期: 2023-09-27 18:00:14

字符串初始化过程中究竟发生了什么?

string s = "Hello World!";

它会调用这些构造函数中的任何一个吗?

public String(char* value);
public String(char[] value);

字符串初始化过程中发生的情况

我查看了CoreCLR存储库,看看ldstr(见Filip Bulovic的回答)在引擎盖下做了什么,发现路径如下:

  1. [vm/interpreter.cpp]解释器的IL评估循环命中case CEE_LDSTR并调用Interpreter::LdStr()
  2. LdStr()调用ConstructStringLiteral并传递当前方法的模块和字符串指针(当前IL指令位置+1)
  3. [vm/jithelpers.cpp] ConstructStringLiteral调用Module::ResolveStringRef
  4. [vm/ceeload.cpp] ResolveStringRef调用InitializeStringData,然后调用LoaderAllocator::GetStringObjRefPtrFromUnicodeString
  5. [vm/loaderallocator.cpp] GetStringObjRefPtrFromUnicodeString调用LoaderAllocator特定的字符串文字映射的GetStringLiteral
  6. [vm/stringliteralmap.cpp]GetStringLiteral对字符串进行散列,并尝试从本地字符串条目散列表中获取字符串对象。如果找到,则返回哈希表中的字符串对象。如果没有,则尝试从全局字符串文字映射中获取字符串对象。如果在全局映射中找不到文字,则会使用GlobalStringLiteralMap::AddStringLiteral将其添加到全局映射中
  7. AddStringLiteral通过调用AllocateStringObject创建COM+字符串对象,为其分配对象句柄,并将文本作为键添加到表中,将对象作为值添加到表。
    • AllocateStringObject:对char计数进行计数,调用垃圾收集器来分配该大小的字符串,将字符串常量复制到COM+字符串对象,用GetIsOnlyLowChars测试字符串对象,如果为true,标志STRING_STATE_FAST_OPS是在COM+字符串对象"…"中设置的,它指示字符串是否可以快速排序。该标志将持久化到包含字符串文字的程序集。当我们从程序集加载字符串时,我们将恢复该标志…
      • GetIsOnlyLowCharsONLY_LOW_CHARS_MASK(即0x80000000)和字符串中的字符进行逐位AND运算,如果字符串仅包含小于0x80的字符,则返回true。托管(内部)方法String.IsFastSort()ref|srcString.IsAscii()ref|src利用了这一点
  8. 一直回到[vm/pinterpreter.cpp]:字符串对象句柄被推送到堆栈

总之,字符串文字采用了一个非常特定的路径,它不会对托管String(char *)String(char[])构造函数进行任何调用。然而,我还没有找到这些构造函数的实现,所以我只能假设它们在某个时刻都调用了AllocateStringObject

我希望这个答案符合你的"完全"的想法。

这里是C#:

public static void Main (string[] args)
{
    string hello = "Hello World!";
    Console.WriteLine (hello);
}

这是IL:

// method line 2
.method public static hidebysig 
       default void Main (string[] args)  cil managed 
{
    // Method begins at RVA 0x20f4
.entrypoint
// Code size 13 (0xd)
.maxstack 2
.locals init (
    string  V_0)
IL_0000:  ldstr "Hello World!"
IL_0005:  stloc.0 
IL_0006:  ldloc.0 
IL_0007:  call void class [mscorlib]System.Console::WriteLine(string)
IL_000c:  ret 
} // end of method MainClass::Main

ldstr指令将对象引用(类型O)推送到新的字符串对象,表示存储在元数据。ldstr指令为内存,并执行转换所需的任何格式转换字符串文字从文件中使用的形式转换为字符串格式运行时需要。

相关文章: