簡體   English   中英

在 C# 中分配內存實際上並不是在分配內存

[英]Allocating memory in C# is not actually allocating memory

當我聲明一個新的字節數組時,內存使用量不會增加。

byte[] test = new[1024*100];

只有在我遍歷每個字節之后,它才真正開始占用 ram。

我怎樣才能讓它實際提交內存而不必先使用它?

我將此用作帶有 try catch 塊的測試,以查看它是否無法分配內存,從而告訴我我的應用程序內存不足,不應嘗試分配任何新對象。

編輯:由於我將要分配的對象與垃圾收集器和堆棧一起使用,我不想使用 malloc 進行分配,因為它可能會在那里成功,但在嘗試分配新的托管對象時會失敗。

好吧,如果你真的想映射所有的內存,那么通過數組重復並用零填充它。 反正都是線性時間。 Array.Clear使用Array.Clear C# 確實不是為這種內存優化而設計的。 您應該關心的唯一資源是未損壞的資源。 在 C# 中考慮剩余內存消耗的正確方法是根本不考慮它。 老實說,在搜索這個問題之前,我不知道 C# 如何在數組聲明期間處理內存分配,這就是重點,我沒有使用高級抽象語言來關心這些東西。 只有當您的應用程序遇到內存瓶頸並且需要優化時,它才有意義。

一個stackalloc運營商,您也許可以彎曲到您的使用,但它是一個不安全的操作。 還有GC.GetTotalMemory() ,它可以顯示當前的內存使用情況(托管對象的),以及Microsoft.VisualBasic.Devices.ComputerInfo.TotalPhysicalMemory ,它會給你機器的總 RAM(不要介意 VB在名稱中,它是一個 .NET Framework 方法,只需添加對Microsoft.VisualBasic.Devices的引用),因此使用它您可以實現您的目標,即是否有足夠的內存供您分配數組。

更新:

從 C# 7.2 開始,現在允許使用stackalloc而無需使用Span<T>ReadOnlySpan<T>類型進入unsafe上下文。 但是,我無法確定是否需要從堆棧中實際分配stackalloc指令,或者如果分配的緩沖區未使用,是否可以省略它,因此可能仍然需要實際遍歷緩沖區以誘使編譯器進入認為需要分配。

如果你想讓它分配所有的字節,你可以使用 Array.Clear,它會用 0 填充所有值

Array.Clear(test, 0, test.Length);

這個簡單的控制台應用程序可讓您在創建和填充 clear 時監控內存使用情況

class Program
{
    static void Main(string[] args)
    {
        //Memory usage 7.1 MB
        Console.WriteLine("Hit enter to allocate");
        Console.ReadKey();
        byte[] data = new byte[1024*1024]; //Memory still 7.1 MB
        Console.WriteLine("Hit Enter to Fill with zeros!");
        Console.ReadKey();
        Array.Clear(data, 0, data.Length); //Memory now 8.1 MB
        Console.WriteLine("1MB filled, hit enter to exit");
        Console.ReadKey();
    }
}

制作了一個函數,該函數將嘗試實際分配我指定的內存(如果不可能,則拋出異常而不是撒謊),如果成功,垃圾收集器將立即收集。

bool IsMemoryAvailable(int amount)
{
    int size = (int)Math.Sqrt(amount) / 2;

    try
    {
        using (Bitmap bmpTest = new Bitmap(size, size))
        {

        }

        GC.Collect();

        return true;
    }
    catch(Exception x)
    {
        return false;
    }
}

如果您遷移到 .NET 6,您可以利用新引入的 NativeMemory 方法使用 C API 分配本機內存:

using System.Runtime.InteropServices;

unsafe
{
    byte* buffer = (byte*)NativeMemory.Alloc(200);

    NativeMemory.Free(buffer);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM