动态堆分配混乱

时间:2017-04-27 02:00:17

标签: memory-management x86 heap masm irvine32

以下是Assembly Kip Irvine一书中提供的代码。 我想知道这段代码在做什么。我明白了 getProcessHeap返回程序现有的32位整数句柄 EAX中的堆区域。如果该功能被取代,它将返回 EAX中堆的句柄。如果失败,则返回EAX中的值 是NULL

HeapAlloc从堆中分配一块内存。如果成功, EAX中的返回值包含内存块的地址。如果它 失败,EAX中返回的值为NULL。

如何在CALLOC中使用字符分配?

如何在IALLOC中使用整数分配?

Hoe是LALLOC中使用的长整数分配吗?

在MALLOC中,如何从堆中分配大小(以字节为单位)?感谢

INCLUDE Irvine32.inc 

HANDLE          TEXTEQU  <WORD> 

GetProcessHeap  PROTO 



HeapAlloc       PROTO, 
                hHeap : HANDLE, 
                dwflags: DWORD, 
                dwbytes: DWORD

HeapFree        PROTO, 
                hHeap : HANDLE,
                dwflags: DWORD,
                lpmem : DWORD 

.data 

hHeap HANDLE ? 

.code 

CALLOC          MACRO size  
                mov   eax, sizeof BYTE 
                imul  eax, size

                push  eax 
                call  MALLOC 
                ENDM 

IALLOC          MACRO size 
                mov   eax, sizeof WORD 
                imul  eax, size 

                push  eax 
                call  MALLOC 
                ENDM 

LALLOC          MACRO   size 
                mov     eax, sizeof DWORD 
                imul    eax, size 

                push    eax 
                call MALLOC 
                ENDM

MALLOC          PROC 
                push        ebp
                mov         ebp, esp 

                invoke      GetProcessHeap 
                invoke      HeapAlloc, eax, 8, [ebp + 8]

                pop     ebp 
                ret     4

MALLOC          ENDP 

MEMFREE         PROC 
                push    ebp 
                mov     ebp, esp 

                invoke  GetProcessHeap 
                invoke  HeapFree, eax, 0, [ebp + 8]

                pop     ebp 
                ret     4 
MEMFREE         ENDP

1 个答案:

答案 0 :(得分:1)

尽管您对这些函数的描述基本上是正确的,但值得指出的是GetProcessHeapHeapAllocHeapFree函数实际上是Win32 API函数,这意味着它们是提供的作为应用程序调用的操作系统的一部分。 Irvine的图书馆刚刚为这些功能提供了原型,使它们更容易调用。因此,可以通过阅读Microsoft的MSDN文档(上面的链接)直接从马的口中获得这些功能的语义。

与文档解释的一样,对于需要分配大量内存以从进程的默认堆中获取内存的应用程序来说,这是一种常见模式。这节省了管理单独的私有堆的创建和开销的需要,只是为了进行分配。 HeapAllocHeapFree(以及类似命名的)函数是您应该在现代Windows编程中使用的函数,而不是您有时仍在Windows编程中使用或引用的obsolete GlobalAlloc or LocalAlloc functions函数本世纪尚未更新的材料。

现在,在您拥有的代码中,由于所有内容最终都会回到MALLOC,所以让我们从那里开始。它设置一个堆栈帧,调用GetProcessHeap,调用HeapAlloc,然后拆除堆栈帧。你应该立即看到一个错误。请记住,在您对GetProcessHeapHeapAlloc函数的描述中,您是否仔细描述了如果失败会发生什么?嗯,你是对的;这些函数可能会失败,正确编写的代码应该检查失败并处理它们。这段代码没有。

  

在MALLOC中,如何从堆中分配大小(以字节为单位)?

MALLOC的实现非常简单:它真正做的就是获取进程堆的句柄,然后使用HeapAlloc从该堆分配内存。因此,如果您想知道它是如何工作的,请返回the documentation for HeapAlloc。从这里,我们看到第一个参数是堆的句柄(从GetProcessHeap中的eax返回),第二个参数是控制分配的标志的按位组合(在本例中为8) ,或HEAP_ZERO_MEMORY),第三个参数是要分配的字节数(在本例中为[ebp + 8])。

[ebp + 8]读取传递给堆栈上MALLOC函数的第一个(也可能是唯一的)参数。 ([ebp + 4]是指向调用函数的指针(MALLOCret),[ebp + 0]ebp的原始值,在进入MALLOC功能。)

在我看来,这是MALLOC函数的另一个(次要)错误:它没有充分记录!我们怎么知道它需要一个参数,更不用说参数的大小/类型和含义,而不是深入到它的实现?函数的基本用途和界面应该在代码中使用注释记录在中。

所以,你的问题的答案是,MALLOC分配你要求它分配的字节数。

  

如何在CALLOC中使用字符分配?

这是一个围绕MALLOC函数的简单宏。其目的基本上是根据要为其分配空间的字符数确定要分配的字节数,然后将该值作为参数传递给MALLOC

CALLOC宏采用单个参数size,这是您要为其分配空间的字符数。 (顺便说一下,我认为size对于此参数的名称选择不佳,因为它不具有描述性。)

然后将调用者指定的size乘以字符所需的实际字节数,该字符在汇编时由表达式sizeof BYTE确定。这将给出实际需要分配的字节数。 (现在,因为sizeof BYTE只是1,所以这是非常愚蠢和低效的代码!我猜它被写成&#34;可移植&#34;,但是用它的汇编语言!)

最后,它将结果(要分配的字节数)压入堆栈并调用MALLOC进行分配。

现在您已了解CALLOC的工作原理,您应该了解这些*ALLOC宏的所有是如何工作的,因为它们完全相同。 IALLOC将其参数乘以短整数(sizeof WORD)的大小,以得到需要分配的实际字节数,而LALLOC将其参数乘以a的大小长整数(sizeof DWORD)。

(注意,虽然这些其他宏的乘法是必要的,但它们效率也很低。sizeof WORD == 2,所以你可以只做左移1.或者,更好的是,另外一个它本身的值。sizeof DWORD == 4,因此左移2。加法和移位比乘法更快。)