全能编程开发工程师的必备技能——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/n/244634.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 13:03
下一篇 2024-12-12 13:03

相关推荐

发表回复

登录后才能评论