内存分配详解 malloc, new, HeapAlloc, VirtualAlloc,GlobalAlloc

  很多地方都会使用内存,内存使用过程中操作不当就容易崩溃,无法运行程序,上网Google学习一下,了解整理下他们之间的区别以及使用 ,获益匪浅

0x01 各自的定义和理解

   (1)先看GlobalAlloc()

    GlobalAlloc()主要用于Win32应用程序实现从全局堆中分配出内存供2017-03-05程序使用,是16位WINDOWS程序使用的API,对应于系统的全局栈,返回一个内存句柄,在实际需要使用时,用GlobalLock()来实际得到内存 区。但32位WINDOWS系统中全局栈和局部堆的区别已经不存在了,因此不推荐在Win32中使用该函数,应使用新的内存分配函数HeapAlloc()以得到更好的支持,GlobalAlloc()还可以用,主要是为了 兼容。

    一般情况下我们在编程的时候,给应用程序分配的内存都是可以移动的或者是可以丢弃的,这样能使有限的内存资源充分利用,所以,在某一个时候我们分配的那块 内存的地址是不确定的,因为他是可以移动的,所以得先锁定那块内存块,这儿应用程序需要调用API函数GlobalLock函数来锁定句柄。如下: lpMem=GlobalLock(hMem); 这样应用程序才能存取这块内存。所以我们在使用GlobalAllock时,通常搭配使用GlobalLock,当然在不使用内存时,一定记得使用 GlobalUnlock,否则被锁定的内存块一直不能被其他变量使用。

    GlobalAlloc对应的释放空间的函数为GlobalFree。

  (2)HeapAlloc()

    HeapALloc是从堆上分配一块内存,且分配的内存是不可移动的(即如果没有连续的空间能满足分配的大小,程序不能将其他零散的 空间利用起来,从而导致分配失败),该分配方法是从一指定地址开始分配,而不像GloabalAlloc是从全局堆上分配,这个有可能是全局,也有可能是 局部

  (3)malloc()

  是C运行库中的动态内存分配函数,主要用于ANSI C程序中,是标准库函数。WINDOWS程序基本不再使用这种方法进行内存操作,因为它比WINDOWS内存分配函数少了一些特性,如整理内存

  (4)new

标准C++一般使用new语句分配动态的内存空间,需要申请数组时,可以直接使用new int[3]这样的方式,释放该方法申请的内存空间使用对应的delete语句,需要释放的内存空间为一个数组,则使用delete [] ary;这样的方式。

要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问.

new在内部调用malloc来分配内存,delete在内部调用free来释放内存。

  (5)

(1) VirtualAlloc  下面是网友的解释 但我个人的理解这个才是内存申请的鼻祖,所有的内存的申请都感觉默认调用了它

    PVOID VirtualAlloc(PVOID pvAddress, SIZE_T dwSize, DWORD fdwAllocationType, DWORD fdwProtect)

VirtualAlloc是Windows提供的API,通常用来分配大块的内存。例如如果想在进程A和进程B之间通过共享内存的方式实现通信,可以使用该函数(这也是较常用的情况)。不要用该函数实现通常情况的内存分配。该函数的一个重要特性是可以预定指定地址和大小的虚拟内存空间。例如,希望在进程的地址空间中第50MB的地方分配内存,那么将参数 50*1024*`1024 = 52428800 传递给pvAddress,将需要的内存大小传递给dwSize。如果系统有足够大的闲置区域能满足请求,则系统会将该块区域预订下来并返回预订内存的基地址,否则返回NULL。

使用VirtualAlloc分配的内存需要使用VirtualFree来释放。

  0x02 区别与联系

它们之间的区别主要有以下几点:

1、GlobalAlloc()函数在程序的堆中分配一定的内存,是Win16的函数,对应于系统的全局栈,而在Win32中全局栈和局部堆的区别已经不存在了,因此不推荐在Win32中使用该函数。

2、malloc()是标准库函数,而new则是运算符,它们都可以用于申请动态内存。

3、new()实际上调用的是malloc()函数。

4、new运算符除了分配内存,还可以调用构造函数,但是malloc()函数只负责分配内存。

5、对于非内部数据类型的对象而言,只使用malloc()函数将无法满足动态对象的要求,因为malloc()函数不能完成执行构造函数的任务。

6、malloc(); 和 HeapAlloc(); 都是从堆中分配相应的内存,不同的是一个是c run time的函数,一个是windows系统的函数, 对于windows程序来说,使用HeapAlloc();会比malloc();效率稍稍高一些。

  0x03关于内存的初始化和使用

    

    1、内存分配方式

    内存分配方式有三种:

    (1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在

  。例如全局变量,static变量。

    (2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存

储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

    (3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自

己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

    

    2.内存使用错误
      发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。

而这些错误大多没有明显的症状,时隐时现,增加了改错的难度。有时用户怒气冲冲地把你找来,程序却没有

发生任何问题,你一走,错误又发作了。 常见的内存错误及其对策如下:
       * 内存分配未成功,却使用了它。

  编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查

指针是否为NULL。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

  * 内存分配虽然成功,但是尚未初始化就引用它。

  犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值

错误(例如数组)。 内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不

可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。

  * 内存分配成功并且已经初始化,但操作越过了内存的边界。

  例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞

错,导致数组操作越界。

  * 忘记了释放内存,造成内存泄露。

  含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次

程序突然死掉,系统出现提示:内存耗尽。

  动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误

(new/delete同理)。

  * 释放了内存却继续使用它。
 
  有三种情况:

  (1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新

设计数据结构,从根本上解决对象管理的混乱局面。

  (2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函

数体结束时被自动销毁。

  (3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。

  【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存

  【规则2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

  【规则3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。

  【规则4】动态内存的申请与释放必须配对,防止内存泄漏。

  【规则5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。

 

 

这些都是我查阅资料的整理 希望会有所帮助

转载于:https://www.cnblogs.com/arsense/p/6505690.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/255225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑盒测试

引言: 什么是黑盒测试呢!? 像我一样的测试小白就会望文生义了:对黑盒子测试 那么黑盒子是什么!? 思考5秒后,得出了这样的答案:黑盒子就是黑色的盒子,嘿嘿! 正文&#xf…

HALCON示例程序classify_image_class_mlp.hdev如何使用MLP分类器分割RGB图像

HALCON示例程序classify_image_class_mlp.hdev如何使用MLP分类器分割RGB图像 示例程序源码(加注释) 关于显示相关显示在其他帖子有介绍。 dev_update_off () dev_close_window () dev_open_window (0, 0, 735, 485, ‘black’, WindowHandle) set_disp…

Expo大作战(十二)--expo中的自定义样式Custom font,以及expo中的路由RouteNavigation

简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻个人修改补充…

悬浮按钮

效果图 //将dp转换为px public static int dip2px(Context context, float dpValue) {final float scale context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale 0.5f); }//浮动图片监听 private void initListener() {//弹出对话框jianwen.set…

HALCON示例程序classify_image_class_svm.hdev使用SVM分类器对多通道图像进行分类

HALCON示例程序classify_image_class_svm.hdev使用SVM分类器对多通道图像进行分类 示例程序源码(加注释) 由于关于SVM分类器的使用之前的贴子介绍过,所以关于SVM的函数,直接点击函数可跳转到之前的介绍贴子。 显示函数解释 dev…

React Native实现NbaApp

rnNba 介绍 本项目为react-native构建的Nba App 设计灵感参考于:灵感来源( 其实就是参考样式 功能简单了很多,因为比较懒233333 功能 nba比分查询球员数据查询球队排名查询项目地址

图像坐标:我想和世界坐标谈谈(A) 【计算机视觉学习笔记--双目视觉几何框架系列】

玉米竭力用轻松具体的描述来讲述双目三维重建中的一些数学问题。希望这样的方式让大家以一个轻松的心态阅读玉米的《计算机视觉学习笔记》双目视觉数学架构系列博客。这个系列博客旨在捋顺一下已标定的双目视觉中的数学主线。数学推导是有着几分枯燥的,但奇妙的计算…

冲刺总结博客

项目预期计划 完美的完成我们的耿丹师生基本信息管理系统,可以实现增删改查等功能,能运用到我们学校里去。 实际进展 实现了增删改查功能,但是要是真的运用到学校中去,功能还是太单一。 过程体会 这个项目是我们小组成立之后&…

img

转载于:https://www.cnblogs.com/SoulCode/p/6508720.html

HALCON示例程序clip.hdev曲别针方向识别

HALCON示例程序clip.hdev曲别针方向识别 示例程序源码(加注释) 关于显示类函数解释 dev_update_window (‘off’) 读入图片 read_image (Clip, ‘clip’) 获得图片尺寸大小 get_image_size (Clip, Width, Height) dev_close_window () dev_open_windo…

图像坐标:我想和世界坐标谈谈(B)

二、图像坐标:我想和世界坐标谈谈(B) 玉米将在这篇博文中,对图像坐标与世界坐标的这场对话中涉及的第二个问题:谈话方式,进行总结。世界坐标是怎样变换进摄像机,投影成图像坐标的呢? 玉米做了一个简单的图示…

c#基础 函数

函数 就是方法 独立完成某项功能的一个个体 函数的的三个好处:1、提高代码的重用性。2、提高功能开发的效率,3.提高代码的可维护性。 函数也分为 固定功能函数, 高度抽象函数。高度抽象函数应用比较广泛, 函数的四要素&#…

【Android】Fragment的简单笔记

被虐了,做某公司笔试时,发现自己连个Fragment的生命周期都写不详细。平时敲代码,有开发工具的便利,有网上各大神的文章,就算忘了也很容易的可以查到,但当要自己不借助外界,却发现自己似乎对该知…

HALCON示例程序color_fuses.hdev通过颜色对保险丝进行分类

HALCON示例程序color_fuses.hdev通过颜色对保险丝进行分类 示例程序源码(加注释) 关于显示类函数解释 dev_update_window (‘off’)定义字符串变量并初始化 FuseColors : [‘Orange’,‘Red’,‘Blue’,‘Yellow’,‘Green’] FuseTypes : [5,10,15,20…

三、致敬“张正友标定”

三、致敬“张正友标定” 此处“张正友标定”又称“张氏标定”,是指张正友教授于1998年提出的单平面棋盘格的摄像机标定方法。张氏标定法已经作为工具箱或封装好的函数被广泛应用。张氏标定的原文为“A Flexible New Technique forCamera Calibration”。此文中所提到…

Using KernelShark to analyze the real-time scheduler【转】

转自:https://lwn.net/Articles/425583/ This article brought to you by LWN subscribers Subscribers to LWN.net made this article — and everything that surrounds it — possible. If you appreciate our content, please buy a subscription and make the …

无缝滚动的算法

一早上的时间做了一个简单的无缝滚动,遇到的问题特别的多,而且对无缝滚动的算法也不是特别的清楚。 无缝滚动效果的原理:就是几个图片 浮动成为一排;然后让图片滚动,正常情况下图片滚完,就留下了后面的空白…

ACM题目————一笔画问题

描述 zyc从小就比较喜欢玩一些小游戏&#xff0c;其中就包括画一笔画&#xff0c;他想请你帮他写一个程序&#xff0c;判断一个图是否能够用一笔画下来。 规定&#xff0c;所有的边都只能画一次&#xff0c;不能重复画。 输入第一行只有一个正整数N(N<10)表示测试数据的组数…

HALCON示例程序color_fuses_lut_trans.hdev通过颜色对保险丝进行分类

HALCON示例程序color_fuses_lut_trans.hdev通过颜色对保险丝进行分类 示例程序源码&#xff08;加注释&#xff09; 关于显示类函数解释 dev_update_off ()定义变量并初始化&#xff0c;这些变量都是下边识别要用到的 FuseColors : [‘Orange’,‘Red’,‘Blue’,‘Yellow’,…

上海电驱动

从行业前景上来说还可以&#xff0c;但这个公司不行&#xff0c;公司各种坑&#xff0c;从上到下各种腐败&#xff0c;打酱油的人比较多&#xff0c;在薪资方面除了技术部稍好一点&#xff0c;其他部门我建议你最好别去了&#xff0c;整体上这个公司员工没幸福感&#xff01;只…