我已经在各种链接上搜索过这个,但仍然存在疑问.
我不明白LocalAlloc
vs GlobalAlloc
vs malloc
vs 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函数.使用HeapAlloc
with GetProcessHeap
而不是malloc
包括重载new
和delete
运算符来使用它,允许你在模块之间传递动态分配的对象,如果内存在一个模块的代码中分配并且在另一个模块的代码中释放,则不必担心内存损坏.指向内存块的指针已传递到外部模块.
Billy ONeal.. 18
GlobalAlloc
并且LocalAlloc
是16位时代的旧功能.不同之处在于,您有时必须能够分配仅在您的段中使用的内存(使用近指针),有时需要分配内存以与系统上的其他进程和段共享.今天,这些家伙以某种形式转发到HeapXxx功能,例如HeapAlloc
.如果您正在编写新代码并且需要避免与C运行时链接,则应使用HeapXxx函数.当然,如果您调用其中任何一个,您的程序将只在Windows上编译和运行.
malloc
是"运行时依赖",使用它需要您链接C运行时(CRT).CRT是包含所有其他标准C库函数的库,如printf
或qsort
.您可以编写一个简单的Win32 API程序而不与此链接(但我真的不明白为什么你想在真实的软件中这样做).
new
是编译器依赖和语言相关的,因为它们需要一个可以编译C++的编译器.(并且通常new
是以实现方式实现的malloc
,所以它可能也需要使用CRT)
摘自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函数.使用HeapAlloc
with GetProcessHeap
而不是malloc
包括重载new
和delete
运算符来使用它,允许你在模块之间传递动态分配的对象,如果内存在一个模块的代码中分配并且在另一个模块的代码中释放,则不必担心内存损坏.指向内存块的指针已传递到外部模块.
GlobalAlloc
并且LocalAlloc
是16位时代的旧功能.不同之处在于,您有时必须能够分配仅在您的段中使用的内存(使用近指针),有时需要分配内存以与系统上的其他进程和段共享.今天,这些家伙以某种形式转发到HeapXxx功能,例如HeapAlloc
.如果您正在编写新代码并且需要避免与C运行时链接,则应使用HeapXxx函数.当然,如果您调用其中任何一个,您的程序将只在Windows上编译和运行.
malloc
是"运行时依赖",使用它需要您链接C运行时(CRT).CRT是包含所有其他标准C库函数的库,如printf
或qsort
.您可以编写一个简单的Win32 API程序而不与此链接(但我真的不明白为什么你想在真实的软件中这样做).
new
是编译器依赖和语言相关的,因为它们需要一个可以编译C++的编译器.(并且通常new
是以实现方式实现的malloc
,所以它可能也需要使用CRT)