当前位置:  开发笔记 > 编程语言 > 正文

LocalAlloc Vs GlobalAlloc Vs malloc Vs new

如何解决《LocalAllocVsGlobalAllocVsmallocVsnew》经验,为你挑选了2个好方法。

我已经在各种链接上搜索过这个,但仍然存在疑问.

我不明白LocalAllocvs GlobalAllocvs mallocvs new内存分配的区别.

我已经浏览了MSDN的这个链接:

比较内存分配方法

请解释以下声明:

的malloc函数有被运行时依赖的缺点.在新的运营商有被依赖编译器和语言相关的缺点

Abhineet.. 21

摘自Raymond Chen的OldNewThing

早在16位Windows的时代,差异就很大了.

在16位Windows中,通过称为"选择器"的值访问内存,每个值可以达到64K.有一个名为"数据选择器"的默认选择器; 对数据选择器执行对所谓的"近指针"的操作.例如,如果你有一个近端指针p的值为0x1234而你的数据选择器是0x012F,那么当你写*p时,你正在访问012F:1234的内存.(当你声明一个指针时,它默认是接近的.如果你想要一个远指针,你必须明确地说FAR.)

重要说明:近指针总是相对于选择器,通常是数据选择器.

GlobalAlloc函数分配了一个选择器,可用于访问您请求的内存量.您可以使用"远指针"访问该选择器中的内存."远指针"是与近指针组合的选择器.(请记住,near指针是相对于选择器的;当你将near指针与适当的选择器结合使用时,你得到一个远指针.)

程序和DLL的每个实例都有自己的数据选择器,称为HINSTANCE.因此,如果您有一个近指针p并通过程序可执行文件中的*p访问它,它会访问相对于程序实例的HINSTANCE的内存.如果从DLL访问它,则会获得相对于DLL的HINSTANCE的内存.

因此,在16位Windows中,LocalAlloc和GlobalAlloc功能完全不同!LocalAlloc返回一个near指针,而GlobalAlloc返回一个选择器.

您打算在模块之间传递的指针必须采用"远指针"的形式,因为每个模块都有不同的默认选择器.如果您想将内存的所有权转移到另一个模块,则必须使用GlobalAlloc,因为这允许收件人调用GlobalFree来释放它.

即使在Win32中,也必须小心不要将本地堆与全局堆混淆.从一个分配的内存不能在另一个上释放.随着过渡到Win32,所有关于近端和远端指针的怪异都消失了.但是本地堆函数和全局堆函数仍然是两个不同的堆接口.

此外,您指定的链接清楚地表明,

从32位Windows开始,GlobalAlloc和LocalAlloc实现为使用进程默认堆句柄调用HeapAlloc的包装函数,如果无法分配内存,可以指示HeapAlloc引发异常,这是LocalAlloc无法提供的功能.

对于你对malloc与new的混淆,Billy ONeal的回答非常清楚地总结了这一点.

对于malloc和HeapAlloc之间的区别,David Heffernan和Luis Miguel Huapaya的答案结合起来给出了完美的解决方案::

malloc便携式,标准的一部分.malloc(和其他C运行时堆函数)是模块相关的,这意味着如果您malloc从一个模块(即DLL)调用free代码,那么您应该在同一模块的代码中调用,否则您可能会遭受一些非常糟糕的堆损坏.

HeapAlloc不可移植,它是Windows API函数.使用HeapAllocwith GetProcessHeap而不是malloc包括重载newdelete运算符来使用它,允许你在模块之间传递动态分配的对象,如果内存在一个模块的代码中分配并且在另一个模块的代码中释放,则不必担心内存损坏.指向内存块的指针已传递到外部模块.


Billy ONeal.. 18

GlobalAlloc并且LocalAlloc是16位时代的旧功能.不同之处在于,您有时必须能够分配仅在您的段中使用的内存(使用近指针),有时需要分配内存以与系统上的其他进程和段共享.今天,这些家伙以某种形式转发到HeapXxx功能,例如HeapAlloc.如果您正在编写新代码并且需要避免与C运行时链接,则应使用HeapXxx函数.当然,如果您调用其中任何一个,您的程序将只在Windows上编译和运行.

malloc是"运行时依赖",使用它需要您链接C运行时(CRT).CRT是包含所有其他标准C库函数的库,如printfqsort.您可以编写一个简单的Win32 API程序而不与此链接(但我真的不明白为什么你想在真实的软件中这样做).

new是编译器依赖和语言相关的,因为它们需要一个可以编译C++的编译器.(并且通常new是以实现方式实现的malloc,所以它可能也需要使用CRT)



1> Abhineet..:

摘自Raymond Chen的OldNewThing

早在16位Windows的时代,差异就很大了.

在16位Windows中,通过称为"选择器"的值访问内存,每个值可以达到64K.有一个名为"数据选择器"的默认选择器; 对数据选择器执行对所谓的"近指针"的操作.例如,如果你有一个近端指针p的值为0x1234而你的数据选择器是0x012F,那么当你写*p时,你正在访问012F:1234的内存.(当你声明一个指针时,它默认是接近的.如果你想要一个远指针,你必须明确地说FAR.)

重要说明:近指针总是相对于选择器,通常是数据选择器.

GlobalAlloc函数分配了一个选择器,可用于访问您请求的内存量.您可以使用"远指针"访问该选择器中的内存."远指针"是与近指针组合的选择器.(请记住,near指针是相对于选择器的;当你将near指针与适当的选择器结合使用时,你得到一个远指针.)

程序和DLL的每个实例都有自己的数据选择器,称为HINSTANCE.因此,如果您有一个近指针p并通过程序可执行文件中的*p访问它,它会访问相对于程序实例的HINSTANCE的内存.如果从DLL访问它,则会获得相对于DLL的HINSTANCE的内存.

因此,在16位Windows中,LocalAlloc和GlobalAlloc功能完全不同!LocalAlloc返回一个near指针,而GlobalAlloc返回一个选择器.

您打算在模块之间传递的指针必须采用"远指针"的形式,因为每个模块都有不同的默认选择器.如果您想将内存的所有权转移到另一个模块,则必须使用GlobalAlloc,因为这允许收件人调用GlobalFree来释放它.

即使在Win32中,也必须小心不要将本地堆与全局堆混淆.从一个分配的内存不能在另一个上释放.随着过渡到Win32,所有关于近端和远端指针的怪异都消失了.但是本地堆函数和全局堆函数仍然是两个不同的堆接口.

此外,您指定的链接清楚地表明,

从32位Windows开始,GlobalAlloc和LocalAlloc实现为使用进程默认堆句柄调用HeapAlloc的包装函数,如果无法分配内存,可以指示HeapAlloc引发异常,这是LocalAlloc无法提供的功能.

对于你对malloc与new的混淆,Billy ONeal的回答非常清楚地总结了这一点.

对于malloc和HeapAlloc之间的区别,David Heffernan和Luis Miguel Huapaya的答案结合起来给出了完美的解决方案::

malloc便携式,标准的一部分.malloc(和其他C运行时堆函数)是模块相关的,这意味着如果您malloc从一个模块(即DLL)调用free代码,那么您应该在同一模块的代码中调用,否则您可能会遭受一些非常糟糕的堆损坏.

HeapAlloc不可移植,它是Windows API函数.使用HeapAllocwith GetProcessHeap而不是malloc包括重载newdelete运算符来使用它,允许你在模块之间传递动态分配的对象,如果内存在一个模块的代码中分配并且在另一个模块的代码中释放,则不必担心内存损坏.指向内存块的指针已传递到外部模块.



2> Billy ONeal..:

GlobalAlloc并且LocalAlloc是16位时代的旧功能.不同之处在于,您有时必须能够分配仅在您的段中使用的内存(使用近指针),有时需要分配内存以与系统上的其他进程和段共享.今天,这些家伙以某种形式转发到HeapXxx功能,例如HeapAlloc.如果您正在编写新代码并且需要避免与C运行时链接,则应使用HeapXxx函数.当然,如果您调用其中任何一个,您的程序将只在Windows上编译和运行.

malloc是"运行时依赖",使用它需要您链接C运行时(CRT).CRT是包含所有其他标准C库函数的库,如printfqsort.您可以编写一个简单的Win32 API程序而不与此链接(但我真的不明白为什么你想在真实的软件中这样做).

new是编译器依赖和语言相关的,因为它们需要一个可以编译C++的编译器.(并且通常new是以实现方式实现的malloc,所以它可能也需要使用CRT)

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有