4

アプリケーションを実行するたびに文字列ポインターの位置が異なるのはなぜStringBuilderですか?

void Main()
{
    string str_01 = "my string";
    string str_02 = GetString();
    unsafe 
    {
        fixed (char* pointerToStr_01 = str_01)
        {
            fixed (char* pointerToStr_02 = str_02)
            {
                Console.WriteLine((Int64)pointerToStr_01);
                Console.WriteLine((Int64)pointerToStr_02);
            }
        }
    }
}

private string GetString()
{
    StringBuilder sb = new StringBuilder();
    sb.Append("my string");

    return sb.ToString();
}

出力:

40907812
178488268

次の時間:

40907812
179023248

次の時間:

40907812
178448964

4

4 に答える 4

13

str_01定数文字列への参照を保持します。StringBuilderただし、文字列インスタンスを動的に構築するため、返される文字列インスタンスは、同じ内容の定数文字列と参照的に同じインスタンスにはなりません。System.Object.ReferenceEquals()戻りfalseます。

は定数文字列への参照であるためstr_01、そのデータはおそらく実行可能ファイルのデータ セクションに格納され、アプリケーションの仮想アドレス空間で常に同じアドレスを取得します。

編集:

PE.Explorerまたは同様のソフトウェアを使用してコンパイルされた .exe ファイルを開くと、UTF-8 エンコーディングの「my string」テキストを確認できます。これは、ファイルの .data セクションにあり、セクションがプロセス仮想メモリにロードされる優先仮想アドレスを含みます。

str_01ただし、おそらく x64 Windows 8.1 がAddress space layout randomization (ASLR)を実行するため、アプリケーションの複数回の実行で同じアドレスを持つことを再現できませんでした。そのため、すべてのポインターは、ロードされた PE セクションを直接指すものであっても、アプリケーションの複数の実行で異なります。

于 2015-01-12T19:15:05.300 に答える
1

2 つの文字列が等しいからといって、それらが同じ参照を指しているわけではありません (これは、同じポインターを持つことを意味すると思います)。C# は、パフォーマンス上の考慮事項などにより、すべての文字列を自動的にインターンしません。両方の文字列のポインターを同じにしたい場合は、 をstr_02使用してインターンできますstring.Intern

于 2015-01-15T09:59:30.393 に答える
1

私がfixedを使用すると、str_01が定数文字列であるためメモリが割り当てられ
、実行時にメモリが割り当てられ、毎回同じ場所を指します

fixed (char* pointerToStr_01 = str_01)

しかし、

fixed (char* pointerToStr_02 = str_02)

メモリを動的に割り当てるため、ポインティング位置は毎回異なります

したがって、実行するたびに文字列ポインターに違いがあります

于 2015-01-20T12:51:22.870 に答える
0

の出力に同意しません

 Console.WriteLine((Int64)pointerToStr_01);

私の主張をより明確にするために個人的にテストしたので、常に同じです。

両方のケースを見てみましょう:

  • 文字列 str_01 = "my string" の場合、この変数のポインター値を出力すると、新しい String オブジェクトが作成されるたびに (つまり、文字列は不変です)、"my string" が割り当てられるため、以前と同じにはなりません。それに。次に、 Fixed ステートメント内で、プログラムを再度実行するとスコープ外のポインターの値が出力され、以前の値は記憶されません。
  • 今までは、StringBuilder の動作を自己説明できると思います。

また、以下を確認してください。

 string str_01 = GetString();
 private static string GetString()
    {
        var sb = new String(new char[] {'m','y',' ','s','t','r','i','n','g'});
        return sb;
    }
于 2015-01-15T10:31:18.130 に答える