vc程序android 广播消息阻塞塞会导致内存耗费增加

22:07 1225人阅读&(2)&&
本文说明两个问题:
1.windows的消息处理机制;
2.怎么往SetTimer的回调函数传递参数。
首先看第一个问题,我们都知道windows是消 息驱动的,windows呈现给用户的任何可以看到听到的东西几乎都是消息驱动的,在底层windows为每个线程准备了一个消息队列,如果用户线程注册 了某个消息,那么在适当的时候windows就会将消息投递到该线程的消息队列中,然后由该线程取出队列中的消息,然后处理之。
这个过程有两个参与者,一 个是windows系统,它主要负责投递消息,收不收是用户线程的事。
另一个就是用户线程,它主要负责取出消息并处理消息,即使用户线程因为睡眠或者根本就没有设定消息循环,系统还是会投递的,系统和用户线程的消息接口就是消息队列,这就在用户和系统之间关于消息解除了耦合,在用户线程处理消息的时候,其实还有一个消息队列,因为一个线程不一定只接收一种消息而且不一定马上就能处理完并返回,这个消息队列我们把它叫做消息分发队列,或者简称分发队列,用来与系统的消息队列区分,注意分发队列里面的消息都是已经格式化后的消息,分发给谁呢?当然是分发给消息的回调函数了,对于有窗口的就是先分发给窗口过程,然后由窗口过程分发给具体的处理函数。
下面我们来通过一个例子说明一下,用vs2005或VC建立一个Win32工程,然后看自动生成的代码:
int APIENTRY _tWinMain(HINSTANCE hInstance,
&&&&&&&&&&&&&&& &&&&&HINSTANCE hPrevInstance,
&&&&&&&&&&&&&&&&&&&& LPTSTR&&& lpCmdLine,
&&&&&&&&&&&&&&&&&&&& int&&&&&& nCmdShow)
&&& // 主消息循环:
&&& while (GetMessage(&msg, NULL, 0, 0))
&&&&&&& if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
&&&&&&&&&&& TranslateMessage(&msg);
&&&&&&&&&&& DispatchMessage(&msg);&&&&& //msg中按照消息号识别
&&& return (int) msg.wP
以上就是消息循环,该线程循环接收消息,然后DispatchMessage消息,Dispatch到窗口过程:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
&&& int wmId, wmE
&&& PAINTSTRUCT
&&& switch (message)&&&&&&&&&&&&&&&&&&&& //message就是消息号
&&& case WM_COMMAND:
&&& default:
&&&&&&& return DefWindowProc(hWnd, message, wParam, lParam);
&&& return 0;
以上实际上就是windows消息机制的全景,对于windows的timer当然也要套用上面的模式了,在SetTimer调用后,实际上就注册了WM_TIMER消息,以下是函数定义:
UINT_PTR SetTimer(&&&&&&
&&& HWND hWnd,
&&& UINT_PTR nIDEvent,
&&& UINT uElapse,
&&& TIMERPROC lpTimerFunc
lpTimerFunc就是回调函数,其形式为:
VOID CALLBACK TimerProc(&&&&&&&&
&&& HWND hwnd,
&&& UINT uMsg,
&&& UINT_PTR idEvent,
&&& DWORD dwTime
SetTimer的参数uElapse就是时间间隔,比如设置为1000即1秒,现在有了一个问题,请看下列代码:
VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
&&& Sleep(5000);
DWORD CALLBACK AutoBakup( PVOID lpParam )
&&& UINT id=SetTimer(NULL,1,1000,TimerFunc);
&&&&&&& BOOL bR
&&& while( ((bRet = GetMessage(&msg,NULL,0,0))!= 0) )
&&&&&&& if(bRet==-1)
&&&&&&&&&&&
&&&&&&& else&
&&&&&&& &&&&TranslateMessage(&msg);
&&&&&&&&&&& DispatchMessage(&msg);
&&& KillTimer(NULL,id);
&&& return 0;
竟然在timer的处理函数中睡眠了,那么SetTimer时的1000毫秒触发一次timer回调还会进行吗?其实不会进行了,本质上那个1000毫秒就 不是说触发回调函数的间隔,而是产生WM_TIMER消息的间隔,因为回调函数中睡眠了,所以也就阻塞了本线程,这个线程就不再往前走了,但是底层的 WM_TIMER消息也会因此而不再投递吗?不会,消息的投递其实不是本线程进行的,而是系统进行的,本线程已经睡眠了,但是系统却没有睡眠,它会继续往该线程的消息队列投递WM_TIMER消息,只不过这些消息不再由该线程的GetMessage取出了,因为它睡眠了(如果对回调函数是否和
GetMessage是否为统一线程有疑义,那么用GetCurrentThreadId()检测一下就好),消息全部堆积在队列里面,然后等待睡眠结束后再一个一个处理。
好吧,这个问题解决了,下一个问题又来了,试着将回调函数改为下面的:
VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
&&& MessageBoxA(NULL,&zhaoya&,&msg&,MB_OK);
&&& Sleep(5000);
发现完全按照SetTimer时设置的那样,1秒弹出一个消息框,一个一个出来,Sleep好像根本就没有执行,线程根本没有睡眠阻塞。
我把 MessageBoxA(NULL,&&,&&,MB_OK)换成printf就不行了,线程立即执行Sleep,这是为何?
关键就在 MessageBoxA上,它实际上是一个模态对话框,既然是对话框它就有消息循环,它并没有开独立的线程,因此可以肯定还是原来的线程,原来 MessageBoxA的内部实现了GetMessage--&TranslateMessage--&DispatchMessage的循环,由于还是原来的线程,所以它GetMessage将还包括WM_TIMER,另外还有消息框自己的一些关于界面的消息,比如WM_PAINT,消息框
的出现只是在系统中又注册了一些需要的消息,就是消息框的关于界面事件的消息。& WM_TIMER回调函数在那,于是调用之,于是又是一个消息框出来了,但 是一旦你点击最上面的OK键,那么程序立即向下进行,进入Sleep,开始睡眠,所有的消息框好像死掉一般,因为就一个线程,它睡眠了,消息循环不再进行,当然所有消息框的消息循环也不再进行,什么WM_PANIT之类的消息都将阻塞,于是消息框们都和死了一样。
通过以上论述,我想关于windows消息大致已经说清了,下面解决第二个问题,如何向SetTimer的回调函数传递自定义参数。
再看TimerProc:
VOID CALLBACK TimerPro(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime);
看 看MSDN关于第三个参数idEvent的解释,就是Timer的id,我们可以用SetTimer的返回值来作为自定义参数的指针,然后在 TimerProc回调函数中通过idEvent取出,强制转换为自己定义的类型,可是SetTimer的返回值并不是我们所能左右的啊,那么还是要从 MSG结构下手了:
typedef struct tagMSG {& &&&// msg
&& WPARAM wP
&& LPARAM lP
看 看wParam和lParam,MSDN上说是额外参数,我们只需要重新设置值就可以了,于是我们要取wParam和lParam这两个参数与 TimerProc形参的交集,这个交集就是我们可以自定义的参数,经过测试,发现wParam其实就是SetTimer返回的id,也就是 TimerProc的形参idEvent,于是例子如下:
VOID CALLBACK TimerFunc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
&&& char * buf = (char*)idE
&&& printf( &%s/n&, buf );//这里打印的就是&abcde&
DWORD CALLBACK AutoBakup( PVOID lpParam )
&&& char * buf = &abcde&;
&&& UINT id=SetTimer(NULL,1,1000,TimerFunc);
&&&&&&& BOOL bR
&&& while( ((bRet = GetMessage(&msg,NULL,0,0))!= 0) )
&&&&&&& if(bRet==-1)
&&&&&&&&&&&
&&&&&&& else&
&&&&&&&&&&& TranslateMessage(&msg);
&&&&&&&&&&& msg.wParam = (WPARAM)//这里设置参数
&&&&&&&&&&& DispatchMessage(&msg);
&&& KillTimer(NULL,id);
&&& return 0;
如果你说,这么把idEvent占了的话,真正的timer的id不就得不到了吗?唉,晕!如果能传递一个指针那么就没有设呢没不能传递了,X位机器上的X 位指针是可以指遍整个虚拟内存的,你可以把自定义参数包装成一个结构,该结构的一个字段指向真正的timer的id,一切...
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:5626次
排名:千里之外
转载:68篇
(4)(1)(1)(3)(3)(4)(1)(5)(9)(40)不知道为什么写的程序运行时,内存一直在增加,导致运行一段时间就会奔溃,该如何处理_VC/MFC大全_优良自学吧 |
当前位置: >
> 不知道为什么写的程序运行时,内存一直在增加,导致运行一段时间就会奔溃,该如何处理优良自学吧提供不知道为什么写的程序运行时,内存一直在增加,导致运行一段时间就会奔溃,该如何处理,不知道为什么写的程序运行时,内存一直在增加,导致运行一段时间就会奔溃原来以为是因为程序一直在接收数据,经过测试在没有数据更新时也存在这个问题。程序中使用了集合类CPtrArray是一个绘图程序,仔细检查每个new的内存块的释放 , GDI资源没有释放吧 ,资源泄漏了吧,这比内存泄露跟可怕不知道为什么写的程序运行时,内存一直在增加,导致运行一段时间就会奔溃原来以为是因为程序一直在接收数据,经过测试在没有数据更新时也存在这个问题。程序中使用了集合类CPtrArray是一个绘图程序------解决方案--------------------仔细检查每个new的内存块的释放
------解决方案--------------------
GDI资源没有释放吧
------解决方案--------------------资源泄漏了吧,这比内存泄露跟可怕(本文来自互联网,不代表搜站(/)的观点和立场)本站所有内容来自互联网,若本站收录的信息无意侵犯了贵司版权,请给我们来信(),我们会及时处理和回复,谢谢编辑推荐最近更新windows(12)
在VC中,基于MFC框架的应用程序由模板生成时,已经自动添加了内存泄漏自动检测功能。当你的程序有内存泄漏,在Debug调式模式下运行就会在vc的输出窗口里显示出来,非常方便我检查程序漏洞。但是当我写一些测试程序时,往往喜欢用控制台程序来编写,但是控制台程序不会自动添加内存泄漏自动检测功能。我在网上搜索了下,找到了添加的方法,经过我的整理把他写出来,希望对我们都有用!
第一步:在程序里定下一下宏(建议定义在stdafx.h头文件中)
#ifdef&_DEBUG
&//for&memory&leak&check
&#define&_CRTDBG_MAP_ALLOC&//使生成的内存dump包含内存块分配的具体代码为止
&#include&&stdlib.h&&
&#include&&crtdbg.h&
&#define&CheckMemoryLeak&_CrtSetDbgFlag(&_CrtSetDbgFlag(&_CRTDBG_REPORT_FLAG&)|&_CRTDBG_LEAK_CHECK_DF)
第二步:在程序的入口处(就是main函数的开头)写如下语句
#ifdef&_DEBUG
&CheckMemoryL
经过这两步我们的控制台程序就已经可以自动检测内存泄漏了。
转载地址:/kylinxh/archive//51457.html
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:8908次
排名:千里之外
原创:29篇
(1)(2)(1)(2)(1)(7)(3)(2)(2)(2)(1)(1)(1)(4)(1)C++基础知识(21)
转:http://blog.csdn.net/klarclm/article/details/7742603
ld 时把所有的目标文件的代码段组合成一个代码段,把所有的数据段组合成一个数据段.
############################################################################
BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。代码段是存放了程序代码的数据,假如机器 中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。
堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时, 新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变 量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以 栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
--------------------------------------------------------------------------------------------------------------------------------------
没初始化的全局变量(bss段),只在编译后生成文件的时候会比初始化的全局变量占空间小。&
加载的时候。如果是大型操作系统上,通常加载器帮你把bss段初始化为0,当然已经初始化的全局变量直接从你的可执行文件拷贝对应的值。要注意,bss全 局变量的地址空间不是加载的时候分配的,同样是链接的时候分配的。&
如果在嵌入式里,很可能没加载器,你的程序是直接由bootload程序加载到内存的。这个时候,bss区域是否被清0,要看写bootload代码的人 了。因为这种bootload通常要自己写的。
--------------------------------------------------------------------------------------------------------------------------------------
BSS是“Block Started by Symbol”的缩写,意为“以符号开始的块”。
  BSS是Unix链接器产生的未初始化数据段。其他的段分别是包含程序代码的“text”段和包含已初始化数据的“data”段。 BSS段的变量只有名称和大小却没有值。此名后来被许多文件格式使用,包括PE。“以符号开始的块”指的是编译器处理未初始化数据的地方。BSS节不包含 任何数据,只是简单的维护开始和结束的地址,以便内存区能在运行时被有效地清零。BSS节在应用程序的二进制映象文件中并不存在。
  在采用段式内存管理的架构中(比如intel的80x86系统),bss段(Block Started by Symbol segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域,一般在初始化时bss 段部分将会清零。bss段属于静态内存分配,即程序一开始就将其清零了。
  比如,在C语言之类的程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。
  text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;而bss段不在可执行 文件中,由系统初始化。
一. 在c中分为这几个存储区
1.栈 - 由编译器自动分配释放
2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
3.全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变 量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放
4.另外还有一个专门放常量的地方。- 程序结束释放
在 函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。在所有函数体外定义的是全局量,加了static修饰符后不管在哪里都存放在全局区(静态区),在 所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。另外,函 数中的&adgfdf&这样的字符串存放在常量区。比如:
int&a&=&0;&//全局初始化区
char&*p1;&//全局未初始化区
void&main()
&&&&int&b;&//栈
&&&&char&s[]&=&&abc&;&//栈
&&&&char&*p2;&//栈
&&&&char&*p3&=&&123456&;&//123456{post.content}在常量区,p3在栈上
&&&&static&int&c&=&0;&//全局(静态)初始化区
&&&&p1&=&(char&*)malloc(10);&//分配得来得10字节的区域在堆区
&&&&p2&=&(char&*)malloc(20);&//分配得来得20字节的区域在堆区
&&&&strcpy(p1,&&123456&);
&&&&//123456{post.content}放在常量区,编译器可能会将它与p3所指向 的&123456&优化成一块
二. 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区
1.栈,就 是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。
2.堆,就 是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在 程序结束后,操作系统会自动回收。
3.自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似 的,不过它是用free来结束自己的生命的。
4.全局/静态存储区,全局变量和静态变量被分配到同一块内存 中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
5.常量 存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改)
三. 谈谈堆与栈的关系与区别
具体地说,现代计算机(串行执行机制),都直接在代 码底层支持栈的数据结构。这体现在,有专门的寄存器指向栈所在的地址,有专门的机器指令完成数据入栈出栈的操作。这种机制的特点是效率高,支持的数据有 限,一般是整数,指针,浮点数等系统直接支持的数据类型,并不直接支持其他的数据结构。因为栈的这种特点,对栈的使用在程序中是非常频繁的。对子程序的调 用就是直接利用栈完成的。机器的call指令里隐含了把返回地址推入栈,然后跳转至子程序地址的操作,而子程序中的ret指令则隐含从堆栈中弹出返回地址
并跳转之的操作。C/C++中的自动变量是直接利用栈的例子,这也就是为什么当函数返回时,该函数的自动变量自动失效的 原因。&
和栈不同,堆的数据结构并不是由系统(无论是机器系统还是操作系统)支持的,而是由函数库提供的。基本的 malloc/realloc/free 函数维护了一套内部的堆数据结构。当程序使用这些函数去获得新的内存空间时,这套函数首先试图从内部堆中寻找可用的内存空间,如果没有可以使用的内存空 间,则试图利用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部堆中去,然后再以适当的形式返回给调用者。当程序释放分配的内 存空间时,这片内存空间被返回内部堆结构中,可能会被适当的处理(比如和其他空闲空间合并成更大的空闲空间),以更适合下一次内存分配申请。这套复杂的分
配机制实际上相当于一个内存分配的缓冲池(Cache),使用这套机制有如下若干原因:
1. 系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配);这样的话对于大量的小内存分类来说会造成浪 费。
2. 系统调用申请内存可能是代价昂贵的。系统调用可能涉及用户态和核心态的转换。
3. 没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。
堆和栈的对比
从以上 知识可知,栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而栈是函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率有一定降 低。栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种。 静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的),也就没有释放函数。为可
移植的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/ 释放内存匹配是良好程序的基本要素。
1.碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间 的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以 至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以&参考数据结构,这里我们就不再一一讨论
2.生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
3.分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由 alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
4.分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈 的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参 考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段
的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
明确区分堆与栈:
在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。
首先,我们举一个例子:
&&&&int*&p=new&int[5];
这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针 p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在
堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下:
&&& push&&&&&&&& 14h
0040102A&&& call&&&&&&&&&&& operator new ()
0040102F&&& add&&&&&&&&& &esp,4
&&& mov&&&&&&&&& dword ptr [ebp-8],eax
&&& mov&&&&&&&&& eax,dword ptr [ebp-8]
&&& mov&&&&&&&&& dword ptr [ebp-4],eax
这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie信息去进行释放内存的工作。
好了,我们回到我们的主题:堆和栈究竟有什么区别?
主要的区别由以下几点:
1、管理方式不同;
2、空间大小不同;
3、能否产生碎片不同;
4、生长方向不同;
5、分配方式不同;
6、分配效率不同;
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小 的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:
打开工程,依次操作菜单如下:Project-&Setting-&Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。
注意:reserve最小值为4Byte;commit是保留在虚 拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。
堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存 的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈 的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。
另外对存取效率的比较:
char&s1[]&=&&aaaaaaaaaaaaaaa&;
char&*s2&=&&bbbbbbbbbbbbbbbbb&;
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定 的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
void&main()
&&&&char&a&=&1;
&&&&char&c[]&=&&&;
&&&&char&*p&=&&;
&&&&a&=&c[1];
&&&&a&=&p[1];
对应的汇编代码
10: a = c[1];
A 4D F1 mov cl,byte ptr [ebp-0Fh]
4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
B 55 EC mov edx,dword ptr [ebp-14h]
A 42 01 mov al,byte ptr [edx+1]
45 FC mov byte ptr [ebp-4],al
第一种在读取时直接就把字 符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了.
无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,就 算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,编写稳定安全的代码才是最重要的
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:158476次
积分:3189
积分:3189
排名:第7581名
原创:127篇
转载:255篇
评论:21条
(101)(47)(49)(63)(20)(2)(20)(14)(9)(5)(3)(14)(33)(3)为什么调整窗口大小后,程序占用内存的数量在增加?该如何处理 - VC/MFC当前位置:& &&&为什么调整窗口大小后,程序占用内存的数量在增加?该为什么调整窗口大小后,程序占用内存的数量在增加?该如何处理&&网友分享于:&&浏览:25次为什么调整窗口大小后,程序占用内存的数量在增加?这是我的ONDRAW函数
这两条语句是在OnDraw中的.
sprintf(m_lpszDate, &%4d年%2d月 &,m_odtCurrentDate.GetYear(), & m_odtCurrentDate.GetMonth());
pDC-& TextOut(int(320 & * & m_fSizeX), & int(BUTTONTOTOP & * & m_fSizeY), & m_lpszDate);
m_lpszDate是在类中定义的成员字符串数组.
可是每次调用OnDraw时,我监视其占用内存的数量,就在一直增加.....
哪位高手给个解决方案?
/********************************************************************************** &
& 绘图函数,实现日历界面的动态 &
& pDC & 系统传送过来的DC,便于绘制客户区 &
& 返回值: &
& 无返回值 &
***********************************************************************************/ &
void & CCalendarView::OnDraw(CDC* & pDC)
CCalendarDoc* & pDoc & = & GetDocument();
ASSERT_VALID(pDoc);
//设置默认焦点为今天
& m_btnDateChange[m_iTaborder].SetFocus();
& //创建设置字体
m_pNewFont & = & new & CF
m_pNewFont-& CreateFont(int(20 & * & m_fSizeY),
int(7 & * & m_fSizeX),
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH & | & FF_SWISS,
_T( &楷体_GB2312 &));
m_pOldFont & = & pDC-& SelectObject(m_pNewFont);
CString & strD
strDate.Format( &%4d年%2d月 &, & m_odtCurrentDate.GetYear(), & m_odtCurrentDate.GetMonth());
& pDC-& TextOut(int(320 & * & m_fSizeX), & int(BUTTONTOTOP & * & m_fSizeY), & strDate);
// delete m_pNewF &
//根据视口变化动态调整按钮控件大小
int & i_Size[5] & = & {50, & 105, & 520, & 610, & 665};
for(int & j=0; & j &5; & j++)
& m_btnDateChange[j].MoveWindow( &
& int(i_Size[j] & * & m_fSizeX), &
& int(BUTTONTOTOP & * & m_fSizeY),
& int(BUTTONWIDTH & * & m_fSizeX),
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有

我要回帖

更多关于 linux 消息队列 阻塞 的文章

 

随机推荐