如何查看一个c 查看程序运行时间所占用的内存空间

程序运行时的内存空间分布
时间: 08:11:54
&&&& 阅读:197
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&我们在写程序时,既有程序的逻辑代码,也有在程序中定义的变量等数据,那么当我们的程序进行时,我们的代码和数据究竟是存放在哪里的呢?下面就来总结一下。
一、程序运行时的内存空间情况
其实在程序运行时,由于内存的管理方式是以页为单位的,而且程序使用的地址都是虚拟地址,当程序要使用内存时,操作系统再把虚拟地址映射到真实的物理内存的地址上。所以在程序中,以虚拟地址来看,数据或代码是一块块地存在于内存中的,通常我们称其为一个段。而且代码和数据是分开存放的,即不储存于同于一个段中,而且各种数据也是分开存放在不同的段中的。
下面以一个简单的程序来看一下在Linux下的程序运行空间情况,代码文件名为space.c
#include &unistd.h&
#include &stdio.h&
int main()
printf(&%d\n&, getpid());
这个程序非常简单,输出当前进程的进程号,然后进入一个死循环,这个死循环的目的只是让程序不退出。而在Linux下有一个目录/proc/$(pid),这个目录保存了进程号为pid的进程运行时的所有信息,其中有一个文件maps,它记录了程序执行过程中的内存空间的情况。编译运行上面的代码,其运行结果如图1所示:
从上面的图中,我们可以看到这样一个简单的程序,在执行时,需要哪些库和哪些空间。上面的图的各列的意思,不一一详述,只对重要的进行说明。
第一列的是一个段的起始地址和结束地址,第二列这个段的权限,第三列段的段内相对偏移量,第六列是这个段所存放的内容所对应的文件。从上图可以看到我们的程序进行首先要加载系统的两个共享库,然后再加载我们写的程序的代码。
对于第二列的权限,r:表示可读,w:表示可写,x:表示可执行,p:表示受保护(即只对本进程有效,不共享),与之相对的是s,意是就是共享。
从上图我们可以非常形象地看到一个程序进行时的内存分布情况。下面我们将会结合上图,进行更加深入的对内存中的数据段的解说。
二、程序运行时内存的各种数据段
该段用来存放没有被初始化或初始化为0的全局变量,因为是全局变量,所以在程序运行的整个生命周期内都存在于内存中。有趣的是这个段中的变量只占用程序运行时的内存空间,而不占用程序文件的储存空间。可以用以下程序来说明这点,文件名为bss.c
#include &stdio.h&
int bss_data[1024 * 1024];
int main()
这个程序非常简单,定义一个4M的全局变量,然后返回。编译成可执行文件bss,并查看可执行文件的文件属性如图2所示:
从可执行文件的大小4774B可以看出,bss数据段(4M)并不占用程序文件的储存空间,在下面的data段中,我们可以看到data段的数据是占用可执行文件的储存空间的。
在图1中,有文件名且属性为rw-p的内存区间,就是bss段。
初始化过的全局变量数据段,该段用来保存初始化了的非0的全局变量,如果全局变量初始化为0,则编译有时会出于优化的考虑,将其放在bss段中。因为也是全局变量,所以在程序运行的整个生命周期内都存在于内存中。与bss段不同的是,data段中的变量既占程序运行时的内存空间,也占程序文件的储存空间。可以用下面的程序来说明,文件名为data.c:
#include &stdio.h&
int data_data[1024 * 1024] = {1};
int main()
这个程序与上面的bss唯一的不同就是全局变量int型数组data_data为每个元素指定了一个初始值1.编译可执行文件data,并查看可执行文件的文件属性如图3所示:
从可执行文件的大小来看,data段数据(data_data数组的大小,4M)占用程序文件的储存空间。
在图1中,有文件名且属性为rw-p的内存区间,就是data段,它与bss段在内存中是共用一段内存的,不同的是,bss段数据不占用文件,而data段数据占用文件储存空间。
3.rodata段
该段是常量数据段,用于存放常量数据,ro就是Read Only之意。但是注意并不是所有的常量都是放在常量数据段的,其特殊情况如下:
1)有些立即数与指令编译在一起直接放在代码段(text段,下面会讲到)中。
2)对于字符串常量,编译器会去掉重复的常量,让程序的每个字符串常量只有一份。
3)有些系统中rodata段是多个进程共享的,目的是为了提高空间的利用率。
在图1中,有文件名的属性为r--p的内存区间就是rodata段。可见他是受保护的,只能被读取,从而提高程序的稳定性。
text段就是代码段,用来存放程序的代码(如函数)和部分整数常量。它与rodata段的主要不同是,text段是可以执行的,而且不被不同的进程共享。
在图1中,有文件名且属性为r-xp的内存区间就是text段。就如我们所知道的那样,代码段是不能被写的。
该段就是栈段,用来保存临时变量和函数参数。程序中的函数调用就是以栈的方式来实现的,通常栈是向下(即向低地址)增长的,当向栈中push一个元素,栈顶指针就会向低地址移动,当从栈中pop一个元素,栈顶指针就会向高地址移动。栈中的数据只在当前函数或下一层函数中有效,当函数返回时,这些数据自动被释放,如果继续对这些数据进行访问,将发生未知的错误。通常我们在程序中定义的不是用malloc系统函数或new出来的变量,都是存放在栈中的。例如,如下函数:
void func()
& & int a = 0;
& & int *n_ptr = malloc(sizeof(int));
& & char *c_ptr =
整型变量a,整型指针变量n_ptr和char型指针变量c_ptr,都存放在栈段中,而n_ptr和c_ptr指向的变量,由于是malloc或new出来的,所以存放在堆中。当函数func返回时,a、n_ptr、c_ptr都会被释放,但是n_ptr和c_ptr指向的内存却不会释放。因为它们是存在于堆中的数据。
在图1中,文件名为stack的内存区间即为栈段。
heap(堆)是最自由的一种内存,它完全由程序来负责内存的管理,包括什么时候申请,什么时候释放,而且对它的使用也没有什么大小的限制。在C/C++中,用alloc系统函数和new申请的内存都存在于heap段中。
以上面的程序为例,它向堆申请了一个int和一个char的内存,因为没有调用free或delete,所以当函数返回时,堆中的int和char变量并没有释放,造成了内存泄漏。
由于在图1所对应的代码中没有使用alloc系统函数或new来申请内存,所以heap段并没有在图1中显示出来,所以以下面的程序来说明heap段的位置,代码文件为heap.c,代码如下:
#include &unistd.h&
#include &stdlib.h&
#include &stdio.h&
int main()
int *n_ptr = malloc(sizeof(int));
printf(&%d\n&, getpid());
free(n_ptr);
查看其运行时内存空间分布如下:
可以看到文件名为heap的内存区间就是heap段。从上图,也可以看出,虽然我们只申请4个字节(sizeof(int))的空间,但是在操作系统中,内存是以页的方式进行管理的,所以在分配heap内存时,还是一次分配就为我们分配了一个页的内存。注:无论是图1,还是上图,都有一些没有文件名的内存区间,其实没用文件名的内存区间表示使用mmap映射的匿名空间。
标签:&&&&&&&&&原文:http://blog.csdn.net/ljianhui/article/details/
教程昨日排行
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!如何查看matlab程序运行所占的总存储空间
在matlab命令窗口执行 feature('memstats')可以查看:物理内存:使用,可用,总数交换页面:使用,可用,总数虚拟内存:使用,可用,总数最大连续可用内存块:按从大到小排序,以及总数命令 whos 和 whos global 可以分别查看所有局部和全局变量占用的内存大小
按下ctrl、alt和delete键进入任务管理器点击“进程”就可以看到每个程序使用内存的情况了
通过任务管理器查看。打开任务管理器,点击进程,下面有一个叫做MATLAB的进程,后面显示了它占用的内存空间。
配置I5处理器,内存4G可以了
你的电脑卡屏或死机的时候,你在电脑干什么呢,能说说吗?我会跟据你说的较为准确的回答你。请将你在卡屏或死机前电脑的表现,和你操作说的详细些,可能就是这些操作引起卡屏或死机的发生,有问题请追问我(我跟据你提供的信息重新回答你)。一般卡屏或死机是自己不正确操作引起的,记住容易引起卡屏或死机的操作不做。电脑不要满负荷操作,就是在玩游戏、看视频时、下载时、看网页的同时在干别的操作最容易重启、死机、蓝屏,因此在玩游戏、看视频、下载时、看网页时不要在操作别的东西了。不管你在干什么,只要一有卡的迹象时就赶紧停止手头的操作退出在试,如果还是这样就不要玩了或是不要看了。硬件方面,如果内存条小就加内存条,CPU等硬件温度过高,硬盘坏道,在有就是加的硬件不合适引起的。卡时要看你做什么引起的,你那样查是没用的。
打开任务管理器,里面有各个进程占用内存的大小!
不要乱卸载,这个可能是给语音软件配套的编译器!!!
呵呵,这个修改m文件,看看哪个变量,假设是x,然后在其赋值语句后面写x,不要分号,这样执行的时候会打印出来的。
人的综合分
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
确定要取消此次报名,退出该活动?> 博客详情
BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
:数据段(data segment)通常是指用来存放程序中
的一块内存区域。数据段属于静态内存分配。
代码段(code segment/text segment)通常是指用来存放
程序执行代码
的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于
, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些
只读的常数变量
,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.
堆(heap)
:堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)
:栈又称堆栈, 存放程序的
(但不包括static声明的变量,
在数据段中
存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。储动态内存分配,需要程序员手工分配,手工释放
下图是APUE中的一个典型C内存空间分布图
#include &stdio.h&
int g1=0, g2=0, g3=0;
int max(int i) { &&& int m1=0,m2,m3=0,*p_ &&& static n1_max=0,n2_max,n3_max=0; &&&& p_max = (int*)malloc(10); &&& printf("打印max程序地址\n"); &&& printf("in max: 0x%08x\n\n",max); &&& printf("打印max传入参数地址\n"); &&& printf("in max: 0x%08x\n\n",&i); &&& printf("打印max函数中静态变量地址\n"); &&& printf("0x%08x\n",&n1_max); //打印各本地变量的内存地址 &&& printf("0x%08x\n",&n2_max); &&& printf("0x%08x\n\n",&n3_max); &&& printf("打印max函数中局部变量地址\n"); &&& printf("0x%08x\n",&m1); //打印各本地变量的内存地址 &&& printf("0x%08x\n",&m2); &&& printf("0x%08x\n\n",&m3); &&& printf("打印max函数中malloc分配地址\n"); &&& printf("0x%08x\n\n",p_max); //打印各本地变量的内存地址
&&& if(i) return 1; &&& else return 0; }
int main(int argc, char **argv) { &&&&static int s1=0, s2, s3=0; &&&&int v1=0, v2, v3=0; &&&&int *p;&&&
&&&&p = (int*)malloc(10);
&&&&printf("打印各全局变量(已初始化)的内存地址\n"); &&&&printf("0x%08x\n",&g1); //打印各全局变量的内存地址 &&&&printf("0x%08x\n",&g2); &&&&printf("0x%08x\n\n",&g3); &&&&printf("======================\n"); &&&&printf("打印程序初始程序main地址\n"); &&&&printf("main: 0x%08x\n\n", main); &&&&printf("打印主参地址\n"); &&&&printf("argv: 0x%08x\n\n",argv); &&&&printf("打印各静态变量的内存地址\n"); &&&&printf("0x%08x\n",&s1); //打印各静态变量的内存地址 &&&&printf("0x%08x\n",&s2); &&&&printf("0x%08x\n\n",&s3); &&&&printf("打印各局部变量的内存地址\n"); &&&&printf("0x%08x\n",&v1); //打印各本地变量的内存地址 &&&&printf("0x%08x\n",&v2); &&&&printf("0x%08x\n\n",&v3); &&&&printf("打印malloc分配的堆地址\n"); &&&&printf("malloc: 0x%08x\n\n",p); &&&&printf("======================\n"); &&& max(v1); &&&&printf("======================\n"); &&&&printf("打印子函数起始地址\n"); &&&&printf("max: 0x%08x\n\n",max); &&&&return 0; }
&打印结果:
可以大致查看整个程序在内存中的分配情况: 可以看出,传入的参数,局部变量,都是在栈顶分布,随着子函数的增多而向下增长. 函数的调用地址(函数运行代码),全局变量,静态变量都是在分配内存的低部存在,而malloc分配的堆则存在于这些内存之上,并向上生长.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在操作系统中,一个进程就是处于执行期的程序(当然包括系统资源),实际上正在执行的程序代码的活标本。那么进程的逻辑地址空间是如何划分的呢?
图1做了简单的说明(Linux系统下的)
左边的是UNIX/LINUX系统的执行文件,右边是对应进程逻辑地址空间的划分情况。
首先是堆栈区(stack),堆栈是由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。栈的申请是由系统自动分配,如在函数内部申请一个局部变量 int h,同时判别所申请空间是否小于栈的剩余空间,如若小于的话,在堆栈中为其开辟空间,为程序提供内存,否则将报异常提示栈溢出。 &&& 其次是堆(heap),堆一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。堆的申请是由程序员自己来操作的,在C中使用malloc函数,而C++中使用new运算符,但是堆的申请过程比较复杂:当系统收到程序的申请时,会遍历记录空闲内存地址的链表,以求寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,此处应该注意的是有些情况下,新申请的内存块的首地址记录本次分配的内存块大小,这样在delete尤其是delete[]时就能正确的释放内存空间。 接着是全局数据区(静态区) (static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 另外文字常量区,常量字符串就是放在这里,程序结束后有系统释放。 最后是程序代码区,放着函数体的二进制代码。
举例说明一下: int a = 0; && && && && && &&&//全局初始化区&
char *p1; && && && && && //全局未初始化区&
int main()&
&&&&&&&& && && && && && // 栈&
&&&&&&&&char s[] = "abc"; && && //栈&
&&&&&&&&char *p2; && && && && //栈&
&&&&&&&&char *p3 = "123456"; &&&//在常量区,而p3在栈上。&
&&&&&&&&static int c =0; && //全局(静态)初始化区&
&&&&&&&&p1 = (char *)malloc(10);
&&&&&&&&p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。&
&&&&&&&&strcpy(p1, "123456"); &&&//放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
&&&&&&&&return 0;
文字常量、初始化的全局变量、static变量都是在data段。未初始化的全局变量是在bss断。
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥linux下,一个运行中的程序,究竟占用了多少存储空间?
RSS列 表示, 程序占用了多少物理内存。 虚拟内存可以不用考虑,它并不占用实际物理内存。 (2). top 命令也可以 其中VIRT(或VSS)列 表示,程序占用了多少虚拟内存。 同 ps aux 中的 VSZ列 RES列 表示, 程序占用了多少物理内存。同 ps aux 中的RSS列 2.在linux下, 查看当前系统占用了多少内存, 一般的命令是 free其中, free就是系统还有多少内存可以使用。但由于 linux 系统对内存使用有一个原则, 就是, 内存是宝贵的, 能使用多少就使用多少。 所以, linux会把已经调用过的包缓存起来,放在内存里。这样,实际上,可以使用的内存,就可以理解为, free+buffers+cached3.当你了解完这些命令以后, 再去使用ps aux 命令去查看的时候, 会发现一个奇怪的现象。 所有的 RSS 列的数据,加起来, 比物理内存的数要大很多。 比如, 物理内存为2G, 而RSS列的数据加起来,可能有5个G之多, 这是怎么回事了? 这是因为RSS列的值骗了我们。 linux的内存机制是这样的: 在运行一个程序时, linux会调用该程序依赖的链接库, 如lib.xx.so。 首先看该链接库是否被映射进内存中,如果没有被映射,则将代码段与数据段映射到内存中,否则只是将其加入进程的地址空间。 这样,当N个程序,依赖到lib.xx.so的时候, 实际上,内存中只有一个lib.xx.so ,而不是N个。 而RSS在显示一个程序占用的实际物理内存时, 将lib.xx.so也算了进来。 比如, X程序, 本身占用内存为5M, lib.xx.so 占用内存2M,lib.xx.so被N个程序共享依赖。 则RSS显示为,X程序运行,占用内存为7M。 实际上, X程序占用了5M空间。 多余的2m被讨入到RSS中了。 当你在用ps aux显示内存占用情况时, N个共享依赖lib.xx.so的N个程序,都把这2m空间,算在自己的RSS中了, 这样RSS的sum值,就比实际物理内存多了。 当然, linux的内存使用机制很复杂, 不是一句两句能说清楚的。这里只是简单的说明了一下, ps aux中的RSS值, 并不能真实反映物理内存的使用情况。 4. 如果查看更详细的内存使用情况, 可用以下几种方法, 或者几种方法结合使用:这几种方法,都需要root账户的权限(1). pmap -d $pid $pid 是正在运行的程序的pid(2). cat /proc/$pid/smaps smaps的数据比较详细,可简单的归纳一下,归纳的命令如下: cat /proc/$pid/smaps | awk '/Size|Rss|Pss|Shared|Private|Referenced|Swap/{val_name=gensub(/([a-zA-Z_]*).*/,&\\1&,1,$1); list[val_name]+=$2; }END{for(val in list)print val,list[val];}' (3). cat /proc/$pid/maps(4). cat /proc/$pid/statm输出解释第一列 size:任务虚拟地址空间大小
第二列 Resident:正在使用的物理内存大小
第三列 Shared:共享页数
第四列 Trs:程序所拥有的可执行虚拟内存大小
第五列 Lrs:被映像倒任务的虚拟内存空间的库的大小
第六列 Drs:程序数据段和用户态的栈的大小
第七列 dt:脏页数量(5). vmstat这个命令据说也可以提供一些参考信息,具体还未研究 5.作为phper,尝试过使用php的函数memory_get_usage(), 该函数也不能得到php当前运行的程序,实际的,真正占用的内存数量。 如果真想得到,php真正占用的内存, 大概只能在, 程序运行的开始,执行一次memory_get_usage(). 在程序运行结束,执行一次memory_get_usage()。 将两者的值相减,得到的值, 应该是一个相对比较准确的,内存占用数量了。 这个方法还没有测试, 考虑到, 得到这个数量,也没有实际意义, 加上平时又比较忙,懒得试了。
里面有很多系统 用XP的就占内存来只占200M内存 开机运行程序可以用360安全卫视优化 他可以帮你禁止那些多余启动项
使用vi打开,在终端输入vi ***.c,然后按Esc :q在终端输入gcc ***.c -o a回车再输入./a回车结果就显示在用户名的前面。
使用top命令
gcc 的编译参数很多,可以查看手册即可按您的编译目的选择编译方式,按一般方法编译之后,可通过指出目标文件的路径来执行,也可以放在环境变量所指出的路径中,直接在终端输入命令执行。
linux下一个c程序的丛生到死:
我不太明白你说的是什么意思,Linux下的C编程一般是通过gcc实现的。例如,创建了一个hello.c文本,在文本中写入#include &stdio.h&
int main(void)
printf(“hello world!!”);
然后在终端输入
$ gcc –o hello hello.c
$ /tmp/hello注:hello.c文件放在/tmp目录下,通过gcc -o hello hello.c命令生成一个hello文件,它是一个可执行文件,然后直接执行,就可以运行该程序了。
不是。这个跟内核有关,你可以自己编译内核
后台程序太多
可能是都是开机启动了
找个xx卫士优化下启动项。
在清理下垃圾。
整理下磁盘碎片。
比如a.cgcc a.c -o 文件路径/agcc ./a文件路径你可以在它的属性里面复制下来直接粘贴上去就可以了。
人的综合分
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
确定要取消此次报名,退出该活动?在MATLAB中查看运行的程序占用了多少内存空间_百度知道
在MATLAB中查看运行的程序占用了多少内存空间
想知道程序所占用的空间,有什么函数可以调用查看吗?我用了memory查看,可是它显示的总是同一个值,我觉得是它显示的是在我程序运行完后,什么都不做时还可用的内存,到底该怎么查看呢,请各位指教!
我有更好的答案
效果相当好!
为什么没人理啊,怎么获得一个算法运行时所使用的内存空间呢?求高手解释啊
用memory命令,显示已经用的内存,还剩的可用内存。会有变化的 。
为您推荐:
其他类似问题
matlab的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 java查看程序运行时间 的文章

 

随机推荐