1

是否有 API 调用或任何其他类似方式,仅使用ntdll.dll, 在堆栈上分配内存?

我知道alloca()这样做,但我不能使用它,因为我只能使用ntdll.dll.

谢谢!

4

3 回答 3

2

alloca 是部分内在函数,由编译器实现。但在内部它调用_alloca_probe_16(对于x86)或__chkstk(x64)在堆栈上向下移动保护页面。此函数的实现存在于子文件夹中alloca16.objchkstk.obj可以在VC子文件夹中找到(其中完全依赖于 VC 版本) - 您可以添加此 obj 以进行链接过程,甚至首先将其转换为 lib。也在最新的 WDK 库中 - 存在ntdllp.lib(不混淆ntdll.lib) - 它还包含所有实现需要(ntdll.dll导出_chkstk(对于 x86)和__chkstk(对于 x64))


再次详细说明:

当你写 src 代码时

alloca(cb) CL编译器在 x86 中生成

mov eax,cb
call _alloca_probe_16 ; do actual stack allocation and probe

在 x64 版本中

mov         ecx,eax 
add         rcx,0Fh 
cmp         rcx,rax 
ja          @@0
mov         rcx,0FFFFFFFFFFFFFF0h 
@@0:
and         rcx,0FFFFFFFFFFFFFFF0h 
mov         rax,rcx 
call        __chkstk ; probe only
sub         rsp,rax ; actual stack allocation

所以_alloca_probe_16和/或__chkstk必须在某处实现,否则您会遇到链接错误 - 未解析的外部符号。

在包含此实现的最新 WDK 版本中存在ntdllp.lib(注意关于p- not )。ntdll.lib在这种情况下,您的 PE 将被导入__chkstk_alloca_probe从中导入ntdll.dll(此函数从 XP 导出的最小值 - 这两个函数都指向相同的代码,只是别名)

另一种解决方案 - 可以在VC文件夹中找到alloca16.obj-chkstk.obj您可以将此 obj 用作链接输入(或在单个 lib 文件中合并alloca16.obj+ )。chkstk.obj在这种情况下,您的 PE 将毫无意义。

于 2016-12-13T18:32:23.543 回答
1

您不需要依赖于架构的东西,因为堆栈上的分配(通常)是独立于架构的。

如果您使用的是 C99,那么您有一个标准的方法,使用可变长度数组:https ://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

你会很简单地写这样的东西:

char mybuffer[my_size];

它将被分配在堆栈上。

于 2016-12-13T18:33:29.777 回答
1

因为alloca操纵堆栈指针,它不是一个“真正的”函数,它是一个“编译器内在”。如果你编译一个使用alloca汇编语言的函数,你应该看到它被直接翻译成sub esp, NNN而不是call alloca. (除了. 之外,可能还有对函数的调用。sub esp, NNN在这种情况下,您需要找出该函数的作用,它通常定义的位置,并安排您的应用程序提供替代。您已经跳过了各种不寻常的箍只使用 NTDLL,这只是另外一个。)

如果你看到并且call allocano sub esp, NNN,那很可能意味着你的编译器只有一个虚假的实现,alloca没有给你从堆栈分配的内存,你根本不应该使用它。

于 2016-12-13T18:43:19.563 回答