C# 手動管理內存
手動管理內存實驗
本實驗旨在理解 C# 中 unsafe 指標操作與 非託管記憶體(unmanaged memory) 的使用方法,並學會如何使用 NativeMemory.Alloc 分配記憶體、直接操作位元資料、以及使用 Encoding 將 byte 資料正確轉換為字串。
二、實驗環境
- 開發工具:JetBrains Rider / Visual Studio 2022
- .NET SDK:.NET 8.0
- 作業系統:Windows 11 / Linux / macOS
- 專案設定:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
三、實驗程式碼
using System;
using System.Runtime.InteropServices;
using System.Text;
unsafe
{
// 分配 100 bytes 非託管記憶體
void* ptr = NativeMemory.Alloc(100);
try
{
byte* bytes = (byte*)ptr;
// 將 ASCII 字元 '1', '2', '3' 寫入記憶體
bytes[0] = (byte)'1';
bytes[1] = (byte)'2';
bytes[2] = (byte)'3';
bytes[3] = (byte)'\0'; // C-style 字串結尾
// 讀取前 3 bytes 並轉為字串
string text = Encoding.ASCII.GetString(bytes, 3);
Console.WriteLine($"輸出內容:{text}");
}
finally
{
// 釋放非託管記憶體,防止記憶體洩漏
NativeMemory.Free(ptr);
}
}
四、實驗步驟
- 在 .csproj 檔中啟用
true 。 - 使用 NativeMemory.Alloc(100) 分配 100 bytes 非託管記憶體。
- 利用指標 byte* 對該記憶體位置直接操作,寫入字元 '1', '2', '3'。
- 透過 Encoding.ASCII.GetString() 將指定長度的 bytes 轉為字串。
- 輸出結果後,使用 NativeMemory.Free(ptr) 釋放記憶體。
五、實驗結果
執行後輸出:
輸出內容:123
六、結果分析
| 步驟 | 動作說明 | 結果 |
|---|---|---|
NativeMemory.Alloc(100) |
分配 100 bytes 未受 GC 管理的空間 | 成功分配 |
bytes[0] = (byte)'1' 等 |
直接操作指標寫入資料 | 記憶體內容:31 32 33 00(十六進制) |
Encoding.ASCII.GetString(bytes, 3) |
將前 3 bytes 轉為字串 | "123" |
NativeMemory.Free(ptr) |
手動釋放非託管記憶體 | 無洩漏 |
分析:
- 若錯誤地使用 bytes->ToString(),則輸出 "49",因為那是 '1' 的 ASCII 數值。
- 正確轉換方式是透過 Encoding 類別將 byte[] → string。
- NativeMemory 提供比 Marshal.AllocHGlobal 更現代化的低階記憶體控制 API。
- 此實驗說明了 unsafe 區塊允許開發者像 C 語言一樣直接控制記憶體。
- 本實驗展示了 C# 在 unsafe 環境中對非託管記憶體的操作能力。
- 使用 NativeMemory.Alloc 分配記憶體後,可直接透過指標寫入資料。
- 透過 Encoding.GetString() 可將指定的 bytes 區段轉換成字串。
- 雖然 unsafe 操作提供更高的效能與靈活度,但需開發者自行負責記憶體管理,
- 若未釋放記憶體或操作越界,將導致非託管記憶體洩漏或程式崩潰。
✅ 建議:除非在高效能或與原生程式碼互通時,否則應避免大量使用 unsafe。
posted on 2025-11-03 03:26 lamkuanthedev 阅读(4) 评论(0) 收藏 举报
浙公网安备 33010602011771号