《Windows核心编程》---堆管理函数

内存解析(stack,heap,static) 在C/C++中,编译程序占用的内存分成5个部分,它们分别是堆(heap),栈(stack),全局/静态储存区(static) ,常量储存区和程序代码区。栈:由编译器在需要时分配,在不需要的时候自动清除变量的储存区。比如程序中 int,float,char等原始类型定义变量时就是在栈上给变量分配空间,不需malloc也不需free,程序结束时,编译器会自动释放。堆: 就是需要人为申请(malloc,n 阅读详情

Windows的“堆”分为默认堆和私有堆两种。默认堆是在程序初始化时由操作系统自动创建的,所有标准内存管理函数都是在默认堆中申请内存的;而私有堆相当于在默认堆中保留了一大块内存,用堆管理函数可以在这个保留的内存区域中分配内存。一个进程的默认堆只有一个,而私有堆可以被创建多个。

 

默认堆可以直接被使用,而私有堆在使用前需要先创建,使用私有堆有很多好处:

1)可以使用默认堆的函数有多种,而它们可能在不同的线程中同时对默认堆进行操作,为了保持同步,对默认堆的访问是顺序进行的;而私有堆的空间是预留的,不同线程在不同的私有堆中同时分配内存并不会引起冲突,所以整体的运行速度更快。

2)当系统必须在物理内存和页文件之间进行页面交换时,系统的性能会受到很大的影响,在某些情况下,使用私有堆可以防止系统频繁地在物理内存和交换文件之间进行数据交换,因为将经常访问的内存局限在一个小范围地址的话,页面交换就不大可能发生,把频繁访问的大量小块内存放在同一个私有堆中就可以保证它们在内存中的位置更近。

3)使用私有堆有利于封装和保护模块化的程序。当程序包含多个模块时,如果使用标准内存管理函数在默认堆中分配内存,那么所有模块分配的内存块是交叉排列在一起的,如果模块A中的一个错误导致内存操作越界,可能会覆盖模块B使用的内存块,到模块B执行时出错,我们将很难发现错误的源头来自于模块A。而如果让不同模块使用自己的私有堆,那么它们的内存就会完全隔离开了,越界错误就很容易跟踪和定位了。

4)使用私有堆使得大量内存的清理变得方便,在默认堆中分配的内存需要一块块单独释放,但将一个私有堆释放后,在这个堆里的内存就全部被释放掉了。并不需要预先释放堆栈的每个内存块。

 

私有堆的创建和释放:

创建私有堆的函数是HeapCreate:

HANDLE WINAPI HeapCreate(

  __in  DWORD flOptions, //指定堆的属性:

//HEAP_GENERATE_EXCEPTIONS---指定函数失败时返回值,不指定这个标志时,函数失败

//时返回NULL、否则返回一个具体的错误代码

         //HEAP_NO_SERIALIZE---控制对私有堆的访问是否要进行独占性的检测;指定这个标志时,

                            //建立堆时不进行独占性检测,访问速度可以更快

  __in  SIZE_T dwInitialSize, //创建堆时分配给堆的物理内存(堆的内存不足时可以自动扩展)

  __in  SIZE_T dwMaximumSize //能够扩展到的最大物理内存

);

 

如果一个堆不再需要了,可以调用HeapDestroy函数将它释放:

BOOL WINAPI HeapDestroy(

  __in  HANDLE hHeap //堆句柄

);

释放私有堆可以释放堆中包含的所有内存块,也可以将堆占用的物理内存和保留的地址空间全部返还给系统。如果函数运行成功,返回值是TRUE;当在进程终止时没有调用HeapDestry函数将私有堆释放时,系统会自动释放。

 

 

在堆中分配和释放内存块:

如果要在堆中分配内存块,可以使用HeapAlloc函数:

LPVOID WINAPI HeapAlloc(

  __in  HANDLE hHeap, //堆句柄

  __in  DWORD dwFlags, //以下标识的组合:HEAP_NO_SERIALIZE HEAP_GENERATE_EXCEPTIONS

                                     //HEAP_ZERO_MEMORY

  __in  SIZE_T dwBytes //需要分配的内存块的字节数

);

注意,在堆中分配的内存块只能是固定的内存块,不想GlobalAlloc函数一样可以分配可移动的内存块。

 

如果要释放分配到的内存块,可以使用HeapFree函数:

BOOL WINAPI HeapFree(

  __in  HANDLE hHeap, //堆句柄

  __in  DWORD dwFlags,

  __in  LPVOID lpMem //要释放的内存块指针,由HeapAlloc或HeapReAlloc返回

);

 

对于用HeapAlloc分配的内存块,可以使用HeapReAlloc函数重新调整大小:

LPVOID WINAPI HeapReAlloc(

  __in  HANDLE hHeap, //堆句柄

  __in  DWORD dwFlags, //以下标识的组合:HEAP_NO_SERIALIZE | HEAP_GENERATE_EXCEPTIONS

                                     //HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY

  __in  LPVOID lpMem, //内存块指针

  __in  SIZE_T dwBytes //新的大小

);

 

其他堆管理函数:

1)GetProcessHeaps函数用来列出进程中所有的堆:

DWORD WINAPI GetProcessHeaps(

  __in   DWORD NumberOfHeaps, //缓冲区中可以存放句柄的数量

  __out  PHANDLE ProcessHeaps //指向用来接收堆句柄的缓冲区的指针,缓冲区的长度应该等于

                                               //NumberOfHeaps*4字节

);

函数执行后,进程中所有堆的句柄全部返回到缓冲区中,其中也包括默认堆的句柄。

 

GetProcessHeap函数用来获得进程默认堆的句柄:

HANDLE WINAPI GetProcessHeap(void);

 

 

2)HeapWalk函数用来列出一个堆中所有内存块:

BOOL WINAPI HeapWalk(

  __in     HANDLE hHeap, //堆句柄

  __inout  LPPROCESS_HEAP_ENTRY lpEntry //指向一个包含PROCESS_HEAP_ENTRY结构的缓冲区

);

调用HeapWalk函数时,函数每次在PROCESS_HEAP_ENTRY结构中返回一个内存块的信息,如果还有其他内存块,函数返回TRUE,程序可以一直循环调用HeapWalk函数直到函数返回FALSE为止。在多线程程序中使用HeapWalk,必须首先使用HeapLock函数将堆锁定,否则调用会失败。

 

其中PROCESS_HEAP_ENTRY结构如下,它包含了堆元素的信息:

typedef struct _PROCESS_HEAP_ENTRY {

  PVOID lpData; //指向堆元素数据区的指针,初始调用HeapWalk时,应将lpData设为NULL

  DWORD cbData; //堆元素数据区的字节大小

  BYTE  cbOverhead; //

  BYTE  iRegionIndex; //

  WORD  wFlags; //

  union {

    struct {

      HANDLE hMem; //

      DWORD  dwReserved[3]; //

    } Block;

    struct {

      DWORD  dwCommittedSize; //

      DWORD  dwUnCommittedSize; //

      LPVOID lpFirstBlock; //

      LPVOID lpLastBlock; //

    } Region;

  } ;

} PROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY;

 

3)HeapValidate函数用来验证堆的完整性或堆中某个内存块的完整性:

BOOL WINAPI HeapValidate(

  __in      HANDLE hHeap, //要验证的堆句柄

  __in      DWORD dwFlags, //标志位

  __in_opt  LPCVOID lpMem //为NULL,则函数顺序验证堆中所有的内存块;

                                     //指定一个内存块,则只验证这个内存块

);

如果验证结果是内存块都完好无损,函数返回非0值,否则函数返回0。

 

4)HeapLock和HeapUnlock函数用来锁定和解锁堆,这两个函数用于线程的同步:

BOOL WINAPI HeapLock(

  __in  HANDLE hHeap

);

BOOL WINAPI HeapUnlock(

  __in  HANDLE hHeap

);

如果函数执行成功,返回值是非0值,否则返回0。一般来说,很少在程序中使用这两个函数,而总是使用HEAP_NO_SERIALIZE标志来进行同步控制,指定了这个标志的话,HeapAlloc、HeapReAlloc、HeapSize和HeapFree等函数会在内部自己调用HeapLock和HeapUnlock函数。

 

5)HeapSize函数返回堆中某个内存块的大小,这个大小就是使用HeapAlloc以及HeapReAlloc时指定的大小:

SIZE_T WINAPI HeapSize(

  __in  HANDLE hHeap, //堆句柄

  __in  DWORD dwFlags, //标志位

  __in  LPCVOID lpMem //需要返回大小的内存块

);

 

6)HeapCompact函数用于合并堆中的空闲内存块并释放不在使用中的内存页面:

SIZE_T WINAPI HeapCompact(

  __in  HANDLE hHeap,

  __in  DWORD dwFlags

);

 

下面实例代码使用HeapWalk函数来遍历一个堆:

 

#include <windows.h>

#include <tchar.h>

#include <stdio.h>

 

int __cdecl _tmain()

{

    DWORD LastError;

    HANDLE hHeap;

    PROCESS_HEAP_ENTRY Entry;

 

    //

    // Create a new heap with default parameters.

    //

    hHeap = HeapCreate(0, 0, 0);

    if (hHeap == NULL) {

        _tprintf(TEXT("Failed to create a new heap with LastError %d./n"),

                 GetLastError());

        return 1;

    }

 

    //

    // Lock the heap to prevent other threads from accessing the heap

    // during enumeration.

    //

    if (HeapLock(hHeap) == FALSE) {

        _tprintf(TEXT("Failed to lock heap with LastError %d./n"),

                 GetLastError());

        return 1;

    }

 

    _tprintf(TEXT("Walking heap %#p.../n/n"), hHeap);

 

    Entry.lpData = NULL;

    while (HeapWalk(hHeap, &Entry) != FALSE) {

        if ((Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {

            _tprintf(TEXT("Allocated block"));

 

            if ((Entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0) {

                _tprintf(TEXT(", movable with HANDLE %#p"), Entry.Block.hMem);

            }

 

            if ((Entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0) {

                _tprintf(TEXT(", DDESHARE"));

            }

        }

        else if ((Entry.wFlags & PROCESS_HEAP_REGION) != 0) {

            _tprintf(TEXT("Region/n  %d bytes committed/n") /

                     TEXT("  %d bytes uncommitted/n  First block address: %#p/n") /

                     TEXT("  Last block address: %#p/n"),

                     Entry.Region.dwCommittedSize,

                     Entry.Region.dwUnCommittedSize,

                     Entry.Region.lpFirstBlock,

                     Entry.Region.lpLastBlock);

        }

        else if ((Entry.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) != 0) {

            _tprintf(TEXT("Uncommitted range/n"));

        }

        else {

            _tprintf(TEXT("Block/n"));

        }

 

        _tprintf(TEXT("  Data portion begins at: %#p/n  Size: %d bytes/n") /

                 TEXT("  Overhead: %d bytes/n  Region index: %d/n/n"),

                 Entry.lpData,

                 Entry.cbData,

                 Entry.cbOverhead,

                 Entry.iRegionIndex);

    }

    LastError = GetLastError();

    if (LastError != ERROR_NO_MORE_ITEMS) {

        _tprintf(TEXT("HeapWalk failed with LastError %d./n"), LastError);

    }

 

    //

    // Unlock the heap to allow other threads to access the heap after

    // enumeration has completed.

    //

    if (HeapUnlock(hHeap) == FALSE) {

        _tprintf(TEXT("Failed to unlock heap with LastError %d./n"),

                 GetLastError());

    }

 

    //

    // When a process terminates, allocated memory is reclaimed by the operating

    // system so it is not really necessary to call HeapDestroy in this example.

    // However, it may be advisable to call HeapDestroy in a longer running

    // application.

    //

    if (HeapDestroy(hHeap) == FALSE) {

        _tprintf(TEXT("Failed to destroy heap with LastError %d./n"),

                 GetLastError());

    }

 

    return 0;

}

 

下面的实例代码使用GetProcessHeaps函数获得进程中所有堆的句柄:

#include <windows.h>

#include <tchar.h>

#include <stdio.h>

#include <intsafe.h>

 

int __cdecl _tmain()

{

    DWORD NumberOfHeaps;

    DWORD HeapsIndex;

    DWORD HeapsLength;

    HANDLE hDefaultProcessHeap;

    HRESULT Result;

    PHANDLE aHeaps;

    SIZE_T BytesToAllocate;

 

    //

    // Retrieve the number of active heaps for the current process

    // so we can calculate the buffer size needed for the heap handles.

    //

    NumberOfHeaps = GetProcessHeaps(0, NULL);

    if (NumberOfHeaps == 0) {

        _tprintf(TEXT("Failed to retrieve the number of heaps with LastError %d./n"),

                 GetLastError());

        return 1;

    }

 

    //

    // Calculate the buffer size.

    //

    Result = SIZETMult(NumberOfHeaps, sizeof(*aHeaps), &BytesToAllocate);

    if (Result != S_OK) {

        _tprintf(TEXT("SIZETMult failed with HR %d./n"), Result);

        return 1;

    }

 

    //

    // Get a handle to the default process heap.

    //

    hDefaultProcessHeap = GetProcessHeap();

    if (hDefaultProcessHeap == NULL) {

        _tprintf(TEXT("Failed to retrieve the default process heap with LastError %d./n"),

                 GetLastError());

        return 1;

    }

 

    //

    // Allocate the buffer from the default process heap.

    //

    aHeaps = (PHANDLE)HeapAlloc(hDefaultProcessHeap, 0, BytesToAllocate);

    if (aHeaps == NULL) {

        _tprintf(TEXT("HeapAlloc failed to allocate %d bytes./n"),

                 BytesToAllocate);

        return 1;

    }

 

    //

    // Save the original number of heaps because we are going to compare it

    // to the return value of the next GetProcessHeaps call.

    //

    HeapsLength = NumberOfHeaps;

 

    //

    // Retrieve handles to the process heaps and print them to stdout.

    // Note that heap functions should be called only on the default heap of the process

    // or on private heaps that your component creates by calling HeapCreate.

    //

    NumberOfHeaps = GetProcessHeaps(HeapsLength, aHeaps);

    if (NumberOfHeaps == 0) {

        _tprintf(TEXT("Failed to retrieve heaps with LastError %d./n"),

                 GetLastError());

        return 1;

    }

    else if (NumberOfHeaps > HeapsLength) {

 

        //

        // Compare the latest number of heaps with the original number of heaps.

        // If the latest number is larger than the original number, another

        // component has created a new heap and the buffer is too small.

        //

        _tprintf(TEXT("Another component created a heap between calls. ") /

                 TEXT("Please try again./n"));

        return 1;

    }

 

    _tprintf(TEXT("Process has %d heaps./n"), HeapsLength);

    for (HeapsIndex = 0; HeapsIndex < HeapsLength; ++HeapsIndex) {

        _tprintf(TEXT("Heap %d at address: %#p./n"),

                 HeapsIndex,

                 aHeaps[HeapsIndex]);

    }

 

    //

    // Release memory allocated from default process heap.

    //

    if (HeapFree(hDefaultProcessHeap, 0, aHeaps) == FALSE) {

        _tprintf(TEXT("Failed to free allocation from default process heap./n"));

    }

 

    return 0;

}

 

 

 

 

 

迈德威视相机调用( 基于 Linux系统+ OpenCV ) 迈德威视相机调用( 基于 Linux系统+ OpenCV )前言一、登录迈德威视官网,下载官方SDK二、代码调用与视频帧处理( 基于 OpenCV )总结 前言     此博客记录了迈德威视工业相机在 Linux 系统下的代码调用及其环境配置,通过 OpenCV 对视频帧进行处理。   一、登录迈德威视官网,下载官方SDK      迈德威视官网 : http://www.mindvision.com.cn/     1. 进入官网后,在服务支持中选择软件下载。    2. 选择Linux系统S. 阅读详情

相关推荐

Amesim与Simulink联合仿真:S-Function接口配置与实战避坑指南

本文详细介绍了Amesim与Simulink联合仿真中S-Function接口的配置方法与实战避坑指南。从环境搭建、编译器配置到S-Function接口实战,逐步解析关键步骤与常见问题解决方案,帮助工程师高效实现多领域系统仿真,特别适合汽车、航空航天等复杂系统建模场景。

weixin_29173777的博客 344

Android 内存监测工具 DDMS --> Heap

用 Heap监测应用进程使用内存情况的步骤如下:1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图、Heap视图都是打开的;2. 将手机通过USB链接至电脑,链接时需要确认手机是处于“USB调试”模式,而不是作为“Mass Storage”;3. 链接成功后,在DDMS的Devices视图中将会显示手机设备的序列号,以及设备中正在运行的部分进程信息;4. 点击选中想要监测的进程,比如system_process进程;5. 点击选中Devices视图界面中最上方一排图标中的“Updat

幻影浪子 7万+

GD32F470实战:如何用EXMC+SDRAM搞定LVGL大内存需求(附完整代码)

本文详细介绍了如何在GD32F470微控制器上通过EXMC接口驱动外部SDRAM,以满足LVGL图形库的大内存需求。内容涵盖硬件连接、EXMC时序配置、轻量级内存管理器实现,以及将LVGL帧缓冲和资源无缝集成到SDRAM的实战方法,并提供了完整的代码示例和调试技巧,帮助开发者构建稳定可靠的嵌入式GUI系统。

k9l0m1的博客 442

内存泄漏

1.内存泄漏 1.1 概念 内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。 1.2 内存泄漏的危害 (1)长期运行的程序出现内存泄漏,会使程序占用的内存一直增加,最后就会出现内存耗尽而导致宕机。 (2) ...

qq_42430426的博客 209

SLUB DEBUG 检测slab 内存泄漏

文章介绍如何定位linux 内核中slab 内存泄漏。

一叶知秋的博客 1491

【WRFDA第一期】WRF数据同化概述及资源整理

【WRFDA第一期】WRF数据同化概述及资源整理

WW、forever的博客 1658

windows进程堆内存列表遍历

正如官网所说,HeapWalk性能远高于快照中的Heap32Next接口,实际测试第二种方式也非常拉跨。使用HeapWalk函数行走堆的大小大致是线性的,而使用Heap32Next函数遍走堆的大小大致为二次。即使对于具有 10,000 个分配的适度堆,HeapWalk的运行速度也比Heap32Next快 10,000 倍,同时提供更详细的信息。随着堆大小的增加,性能差异变得更加明显。遍历堆列表 - Win32 apps | Microsoft Learnt=N7T8t=N7T8t=N7T8t=N7T8。

gaojunhuiwww的专栏 1561

YOLOv11改进,YOLOv11引入B2CNet的BFAM(双时相特征聚合模块),JSTARS 2024,二次创新C3k2结构

YOLOv11改进,YOLOv11引入B2CNet的BFAM(双时相特征聚合模块),JSTARS 2024,二次创新C3k2结构

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 406

C语言-基础入门-学习笔记(11):堆管理

C语言-基础入门-学习笔记(11):堆管理 内存区可以分为栈、堆、静态存储区和常量存储区。 局部变量、函数形参、临时变量都是在栈上获得内存的,它们的获取方式都由编译器自动执行。 从堆上获取的空间都是程序员自行管理的。 一、动态内存管理 使用堆管理要包含头文件:stdlib.h 1.分配内存空间 malloc函数可以从堆上获得指定字节数的内存空间,声明如下: void *malloc(int n);...

qq_42826337的博客 1792

【滚雪球学数学建模】第1节·建模入门+三步法+案例

🎓 本文收录于 《滚雪球学数学建模》专栏,本专栏专注于从零基础出发,带你循序渐进掌握数学建模的核心方法与思维路径。通过“滚雪球式”学习法,从最简单的生活化案例到经典建模工具,再到省赛、国赛真题实战演练,逐步积累知识与技能,帮助你搭建完整的建模体系。无论你是刚接触建模的新生,还是希望提升科研与竞赛能力的学者与工程师,本专栏都将为你提供一条清晰、高效、可实操的建模成长路线,助力你快速进阶,突破难点,迈向数学建模竞赛与实际应用的更高峰 🚀!

**My Coding Family** 6412

机器人视觉联动精度优化:从±2mm到±0.02mm,产线级手眼标定全实战

2025年我接东莞长安Type-C接口分拣项目的时候,就是栽在了手眼标定上:实验室里标定完精度±0.5mm,一到产线直接掉到±2mm,机器人10次有3次抓不住,2000多件Type-C接口直接报废,还撞坏了2套汇川SCARA机器人的吸盘,本来45天的工期拖了3个月,不仅没赚到钱,还倒贴了几万块。手眼标定从来不是简单的跑个demo、算个矩阵就完事了,它是一个系统工程:从硬件选型、安装固定、相机标定、标定流程、算法优化、环境控制、重复验证,每一个环节都会影响最终的联动精度。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 384

剖析《Windows 核心编程(第 5 版)》:掌握 Windows 平台高效编程秘诀

Windows 核心编程(第 5 版)》凭借丰富的内容和深入的讲解,为开发者全面展现了 Windows 操作系统的核心编程技术。通过学习这本书,开发者不仅能够深入理解 Windows 操作系统的底层机制,还能掌握在 Windows 平台上进行高效编程的方法和技巧。无论是开发桌面应用程序、服务器端程序,还是进行系统级编程,这本书都能为开发者提供强大的支持和指导。对于渴望在 Windows 平台上提升编程能力的开发者而言,《Windows 核心编程(第 5 版)》无疑是一本不可或缺的技术佳作。

数字魔方操控师的博客 1038

2025年全国青少年信息素养大赛初赛真题(算法创意实践挑战赛C++初中组:文末附答案)

2025年全国青少年信息素养大赛初赛真题(算法创意实践挑战赛C++初中组:文末附答案)

王老师青少年编程 3396

windows 堆管理

windows堆管理是建立在虚拟内存管理的基础之上的,每个进程都有独立的4GB的虚拟地址空间,其中有2GB的属于用户区,保存的是用户程序的数据和代码,而系统在装载程序时会将这部分内存划分为4个段从低地址到高地址依次为静态存储区,代码段,堆段和栈段,其中堆的生长方向是从低地址到高地址,而栈的生长方向是从高地址到低地址。 程序申请堆内存时,系统会在虚拟内存的基础上分配一段内存,然后记录下来这块的大小和

Masimaro的专栏 2523

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

WINDOWS核心编程——Windows内存管理

想要了解Windows内存体系结构首先要对系统的内存的分段分页和进程隔离机制要有所了解。系统为了对进程进行隔离,使得每个进程只能访问自己申请的内存而不能访问其他进程的内存资源,对每个进程的内存使用线性地址编制,在通过内存的分页机制在进程需要访问物理内存时通过进程的页表找到世界的物理内存的地址通过系统读写内存中的数据。在早期总线(20位寻址1M)大于寄存器(16位寻址64k)的情况下为了表示更多的物

pokeyode的专栏 9388

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Windows核心编程

Windows核心编程学习01.Winwods核心编程:字符和字符串处理02.Windows核心编程:内核对象03.Windows核心编程:进程04.Windows核心编程:线程基础05.Windows核心编程:作业06.Windows核心编程:线程调度07.

shenzi的天空 2566

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Window API (三)堆管理操作

Windows 系统中,每个进程都有自己的堆,每个进程的堆的数量也有所不同。Windows系统中所谓的“堆”(Heap)并不是内存块,而是一种用于内存管理的对象,也是一种内存组织的形式。进程可以从属于自己的堆上分配内存和释放内存。      堆的句柄惟一标识了一个堆。在堆上分配内容前,首先需要获得所要进行分配的堆的句柄,获得堆的句柄有两种方式:一种是获取在进程中时已经创建好的堆,二是进程自己再创

阿修罗道 2654

Windows核心编程:堆

作者:shenzi链接:http://blog.youkuaiyun.com/shenziWindows核心编程:堆    堆非常适合分配大量的小型数据。堆得优点是它能让我们专心解决手头上的问题,而不必理会分配粒度和页面边界这类事情。堆得缺点是分配和释放内存块的速度比其它方式慢,而且也无法再对物理存储器的调拨和撤销调拨进行直接

shenzi的天空 2083

《Windows核心编程》读书笔记十八章 堆

第十八章 堆 本章内容 18.1 进程的默认堆 18.2 为什么要创建额外的堆 18.3 如何创建额外的堆 18.4 其他堆函数 与虚拟内存和内存映射文件相比,堆非常适合大量的小型数据。堆是用来管理链表和树的最佳方式。 堆能让我们专心心解决问题,不必理会分配粒度和页面边界的这类很底层的事情。堆的缺点是分配和释放速度比其他方式慢,而且也无法对物理存储器的调拨和撤销进行直接控制。

sesiria的博客 481

Windows堆管理

Windows的堆管理器,负责管理使用页面粒度内存分配函数保留的大内存区中的内存分配。这句话的意思是,堆是基于页粒度内存分配的更高级的内存管理策略。“使用页面粒度内存分配函数保留的大内存区”指的是操作系统底层的内存管理单元。在 Windows 中,虚拟内存管理器以页(Page,通常为 4KB)为基本单位管理物理内存,并且通过 VirtualAlloc等函数分配内存时,实际上是以分配粒度(Allocation Granularity,通常为 64KB)​ 来保留地址空间的。

静下心来,做好每一件事 250

Windows内存管理的API函数

数据所在的内存地址,内存最小存储单元是字节,在32位系统上使用32位数来表示内存地址. 一共可以表示2^32次 地址空间: 32位可以使用4GB内存,那么地址空间就是0x00000000~0xFFFFFFFF 物理内存: 硬件系统中真实存在的存储空间称为物理内存. 虚

bizhu的专栏 8158

WINDOWS核心编程--堆栈

WINDOWS核心编程--堆栈堆栈是大家常常使用的,WINDOWS核心编程中的堆栈的解释比较深度一些。先看看栈:每当创建一个线程时,系统就会为线程的堆栈(每个线程有它自己的堆栈)保留一个堆栈空间区域,并将一些物理存储器提交给这个已保留的区域。按照默认设置(可以修改),系统保留 1MB的地址空间并提交两个页面的内存。因为栈的大小是有限的,因此栈是可能溢出的。特别是在深度嵌套的情况下,如递归调用。

xuwei2007的专栏 987
上一篇: 《Windows核心编程》---获得内存的当前状态のGlobalMemoryStatusEx
下一篇: 《ASCE1885的武术》---搬头
ACE1985
博客等级 码龄17年 1307粉丝 308原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值