全能編程開發工程師的必備技能——globalAlloc詳解

GlobalAlloc是Windows API中的一個函數,它可以用來在本地進程堆中分配指定大小的內存。本文將從多個方面詳細講解globalAlloc。

一、globalAlloc函數

globalAlloc作為一種內存分配函數,其主要作用是在進程堆中分配一塊指定大小的內存,並返回指向分配內存的指針(或空指針)。其函數原型如下:

    HGLOBAL GlobalAlloc(
        UINT uFlags,
        SIZE_T dwBytes
    );

其中,uFlags可以為以下幾種常量:

  • GMEM_FIXED:要求內存分配成功並且分配出來的內存地址不變
  • GMEM_MOVEABLE:要求分配的內存空間可以移動(通過GlobalReAlloc函數)
  • GMEM_ZEROINIT:要求全局分配緩衝區的內部所有位都被初始化為零

dwBytes則代表要分配的內存大小,單位為位元組(Byte)。

二、globalAlloc rust

Rust是一門功能強大的系統編程語言,同樣也可以使用globalAlloc函數。具體使用步驟:

  1. 將以下代碼複製並粘貼至項目根目錄下的Cargo.toml文件:
            [features]
        std = ["alloc_system"]
        
        [dependencies]
        alloc_system = { version = "0.3.2", optional = true }
            
  2. 在源文件中引入alloc庫和globalAlloc:
            #![feature(global_allocator)]
            #![global_allocator]
            static GLOBAL: std::alloc::System = std::alloc::System;
            
  3. 使用globalAlloc:
            use std::alloc::{GlobalAlloc, Layout};
            
            struct MyAllocator;
            unsafe impl GlobalAlloc for MyAllocator {
                unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
                    GlobalAlloc::alloc(&std::alloc::System, layout)
                }
                unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
                    GlobalAlloc::dealloc(&std::alloc::System, ptr, layout)
                }
            }
            
            #[global_allocator]
            static GLOBAL: MyAllocator = MyAllocator;
            
            fn main() {
                let n = 1024*1024;
                let layout = Layout::from_size_align(n, 1).unwrap();
                let ptr = unsafe { GLOBAL.alloc(layout) };
                if ptr.is_null() {
                    panic!("Out of memory");
                }
            }
            

三、globalAlloc和new

對於內存分配,常見的方式除了globalAlloc之外,還有使用new運算符。二者的差異在於,使用new運算符是對於某種類型的內存進行分配,而globalAlloc則是分配了若干個位元組的內存。當然,也可以在globalAlloc之上進行進一步的類型轉換。

    struct MyStruct {
        x: i32,
        y: i32,
    }
    let my_struct = unsafe { 
        let layout = Layout::new::();
        GlobalAlloc::alloc(&SYSTEM_ALLOCATOR, layout) 
        as *mut MyStruct
    };
    *my_struct = MyStruct { x: 1, y: 2 };

四、globalAlloc malloc 多大

在進行內存分配時,需要指定內存大小。但是,如何決定這個內存的大小呢?這與用戶的具體需求有關。如果內存大小太小,可能無法滿足程序的需要;而內存太大則會造成浪費。可以通過用戶提供特定數據的大小等方法進行內存大小的設定。

    const NAME_SIZE: usize = 256;
    let layout = Layout::from_size_align(NAME_SIZE, 1).unwrap();
    let name_ptr = unsafe { GlobalAlloc::alloc(&SYSTEM_ALLOCATOR, layout) };

五、globalAlloc failed

在進行內存分配時,可能會分配失敗。出現分配失敗的原因可能為:內存不足、內存碎片化、PC卡或存儲控制器發生故障等。如果globalAlloc分配失敗,則返回空指針,需要對此進行判斷,如果出現空指針,需要進行相應的錯誤處理。

    let layout = Layout::from_size_align(usize::MAX, 1).unwrap();
    let ptr = unsafe { GlobalAlloc::alloc(&SYSTEM_ALLOCATOR, layout) };
    if ptr.is_null() {
        println!("Allocation failed!");
    }

六、globalAlloc的執行效率

globalAlloc效率高於C++的new或malloc函數,因為globalAlloc使用的是自己的線程安全的堆內存,而C++的new或malloc函數使用的是全局內存。

七、globalAlloc和virtualalloc區別

globalAlloc和virtualalloc都是用來分配內存的函數,但它們的使用場景不同。

globalAlloc在進程的堆中分配內存(Allocates Memory from Process’s Heap),而virtualalloc則用於訪問未分配的虛擬內存(Reserves Pages of Virtual Memory),這個虛擬內存可以是每個進程的專用地址空間(無論是保留還是提交)。因此,當需要在進程的地址空間中分配內存時,請使用globalAlloc;而當需要訪問未分配的虛擬內存時,請使用virtualalloc。

Code

    use std::alloc::{GlobalAlloc, Layout};
    
    struct MyAllocator;
    unsafe impl GlobalAlloc for MyAllocator {
        unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
            GlobalAlloc::alloc(&std::alloc::System, layout)
        }
        unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
            GlobalAlloc::dealloc(&std::alloc::System, ptr, layout)
        }
    }
    
    #[global_allocator]
    static GLOBAL: MyAllocator = MyAllocator;
    
    fn main() {
        let n = 1024*1024;
        let layout = Layout::from_size_align(n, 1).unwrap();
        let ptr = unsafe { GLOBAL.alloc(layout) };
        if ptr.is_null() {
            panic!("Out of memory");
        }
    }

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/244634.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 13:03
下一篇 2024-12-12 13:03

相關推薦

發表回復

登錄後才能評論