精华内容
下载资源
问答
  •  进程(执行的程序)会占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等。不过进程对这些内存的管理方式因内存用途 不一而不尽相同,有些内存是事先静态分配和统一回收的...



    进程虚拟地址空间的5个段示意图





           进程(执行的程序)会占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等。不过进程对这些内存的管理方式因内存用途 不一而不尽相同,有些内存是事先静态分配和统一回收的,而有些却是按需要动态分配和回收的。对任何一个普通进程来讲,它都会涉及到5种不同的数据段。

    Linux进程的五个段

    下面我们来简单归纳一下进程对应的内存空间中所包含的5种不同的数据区都是干什么的。

    BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

    数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

    代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

    堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用new、malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减),若程序员不释放,则会有内存泄漏,系统会不稳定,Windows系统在该进程退出时OS释放,Linux则只在整个系统关闭时OS才去释放(参考Linux内存管理)。

    栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

    它是由操作系统分配的,内存的申请与回收都由OS管理。


    常量区(constant segment)常量字符串就是放在这里的,const char *p = "hello world"; (注意:const只是个编译时概念,不影响编译后的环境,其定义的变量与常量是不同的概念) "hello world" 是具有静态存储期的对象,位于常量区,不能做修改,其生存期是整个程序的运行期间常量所有的常量放在常量区,进程退出时由OS释放

    PS:

    全局的未初始化变量存在于.bss段中,具体体现为一个占位符;全局的已初始化变量存于.data段中;而函数内的自动变量都在栈上分配空间。.bss是不占用.exe文件空间的,其内容由操作系统初始化(清零);而.data却需要占用,其内容由程序初始化,因此造成了上述情况。

    bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。
    data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。 数据段包含经过初始化的全局变量以及它们的值。BSS段的大小从可执行文件中得到 ,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含数据段和BSS段的整个区段此时通常称为数据区。


    需要注意的是,代码段和数据段之间有明确的分隔,但是数据段和堆栈段之间没有,而且栈是向下增长,堆是向上增长的,因此理论上来说堆和栈会“增长到一起”,但是操作系统会防止这样的错误发生,所以不用过分担心。


    static关键字

    1. 全局静态变量

       在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。

       1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)

       2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

       3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。

    看下面关于作用域的程序:
    //teststatic1.c
    void display();
    extern int n;
    int main()
    {
      n = 20;
      printf("%dn",n);
      display();
      return 0;
    }
     
    //teststatic2.c
    static int n;   //定义全局静态变量,自动初始化为0,仅在本文件中可见
    void display()
    {
      n++;
      printf("%dn",n);
    }
     

    文件分别编译通过,但link的时候teststatic2.c中的变量n找不到定义,产生错误。
     
    定义全局静态变量的好处:

    <1>不会被其他文件所访问,修改

    <2>其他文件中可以使用相同名字的变量,不会发生冲突。

    2. 局部静态变量

      在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。

      1)内存中的位置:静态存储区

      2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

      3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

      注:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束,只不过我们不能再对他进行访问。

          当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。

    3. 静态函数

      在函数的返回类型前加上关键字static,函数就被定义成为静态函数。

      函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

      例如:
    //teststatic1.c
    void display();
    static void staticdis();
    int main()
    {
      display();
      staticdis();
      renturn 0;
    }
     
    //teststatic2.c
    void display()
    {
      staticdis();
      printf("display() has been called n");
    }
     
    static void staticdis()
    {
      printf("staticDis() has been calledn");
    }
     
    文件分别编译通过,但是连接的时候找不到函数staticdis()的定义,产生错误。
     实际上编译也未过,vc2003报告teststatic1.c中静态函数staticdis已声明但未定义;
    定义静态函数的好处:

    <1> 其他文件中可以定义相同名字的函数,不会发生冲突

    <2> 静态函数不能被其他文件所用。
     
    存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
     
    auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。

    关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。

    由于static变量的以上特性,可实现一些特定功能。

    1. 统计次数功能

    声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数。这是统计函数被调用次数的最好的办法,因为这个变量是和函数息息相关的,而函数可能在多个不同的地方被调用,所以从调用者的角度来统计比较困难。代码如下:
     
    void count();
    int main()
    {
     int i;
     for (i = 1; i <= 3; i++)
      count();
      return 0;
    }
    void count()
    {
     static num = 0;
     num++;
     printf(" I have been called %d",num,"timesn");
    }

    输出结果为:
    I have been called 1 times.
    I have been called 2 times.
    I have been called 3 times.



    参考资料:

    1. 《数据段、代码段、堆栈段、BSS段的区别》http://blog.csdn.net/jxhui23/article/details/8064766

    2. 《c语言中static 用法总结》http://www.cnblogs.com/hoys/archive/2011/01/19/1939479.html

    展开全文
  • C语言内存监控

    2012-05-17 16:33:49
    C语言监控一个进程(比如QQ)的内存占用情况,整合了网上的一些代码。 头文件"process_stat.h" #ifndef PROCESS_STAT_H  #define PROCESS_STAT_H  #ifdef __cplusplus  extern "C" {  #endif   ...

    用C语言监控一个进程(比如QQ)的内存占用情况,整合了网上的一些代码。

    头文件"process_stat.h"

    #ifndef PROCESS_STAT_H  
    #define PROCESS_STAT_H  


    #ifdef __cplusplus  
    extern "C" {  
    #endif  

     typedef long long           int64_t;  
     typedef unsigned long long  uint64_t;  


    #ifdef  __cplusplus  
    }  
    #endif  

    #endif/*PROCESS_STAT_H*/ 

     


     

    主函数

    #include "stdafx.h"
    #include <stdio.h>
    #include <windows.h>  
    #include <psapi.h>  
    #include <assert.h>  
    #include "process_stat.h"
    #include   "tlhelp32.h "

    UINT GetProcessIdByName(LPCTSTR pszExeFile)
    {
     UINT nProcessID = 0;
     PROCESSENTRY32 pe = {sizeof(PROCESSENTRY32)};

     

     HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
     if (hSnapshot != INVALID_HANDLE_VALUE)
     {
      if (Process32First(hSnapshot, &pe))
      {
       while (Process32Next(hSnapshot, &pe))
       {
        if (lstrcmpi(pszExeFile, pe.szExeFile) == 0)
        {
         nProcessID = pe.th32ProcessID;
         break;
        }
       }
      }

      CloseHandle(hSnapshot);
     }

     return nProcessID;
    }

     

    int get_memory_usage(uint64_t* mem, uint64_t* vmem)  
    {  
        PROCESS_MEMORY_COUNTERS pmc; 

       UINT ID = GetProcessIdByName(_T("QQ.exe"));
        if(GetProcessMemoryInfo(/*GetCurrentProcess()*/OpenProcess(PROCESS_ALL_ACCESS, FALSE, ID), &pmc, sizeof(pmc)))  
        {  
            if(mem) *mem = pmc.WorkingSetSize;  
            if(vmem) *vmem = pmc.PagefileUsage;  
            return 0;  
        }  
        return -1;  
    }

    int _tmain(int argc, _TCHAR* argv[])
    {
     uint64_t mem, vmem, r, w; 
     get_memory_usage(&mem, &vmem);    
     
     printf("内存使用: %u 字节\n", mem);  
     printf("虚拟内存使用: %u 字节\n", vmem);    
     
     return 0;
    }

     

    展开全文
  • 首先要知道,我们在应用程序中所使用的地址均是虚拟内存地址,在32位操作系统中,每一个进程占用的虚拟内存是4G,4G的虚拟内存又分为1G的内核空间和3G的用户空间,内核空间是当前主机中所有进程共有的,...

    C语言变量的内存分配及储存位置的探究

    最近学习C语言,对变量的储存位置很不清楚,后来通过多次查询资料有了自己的见解,特写此博客分享自己对C语言在内存中的储存过程的理解,如有错误望指正。

    一、虚拟内存

    首先要知道,我们在应用程序中所使用的地址均是虚拟内存地址,在32位操作系统中,每一个进程所占用的虚拟内存是4G,4G的虚拟内存又分为1G的内核空间和3G的用户空间,内核空间是当前主机中所有进程共有的,用户空间是当前进程私有的,下面讲解的内存区域的划分,指的是用户空间的划分。
    虚拟内存划分

    二、虚拟内存用户空间的区域划分

    在了解了虚拟内存的基础上,我们继续看用户空间的区域划分。内存主要分为以下五个区域:
    1、栈区(又称堆栈区)
    存放函数的参数值、非静态局部变量等,由编译器自动分配和释放,通常在函数执行完后就释放了,其操作方式类似于数据结构中的栈。栈内存分配运算内置于CPU的指令集,效率很高,但是分配的内存量有限。
    2、堆区
    就是通过malloc动态分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放,如果不在程序中释放则一般整个程序结束后会被系统回收内存资源。分配方式类似于数据结构中的链表。“内存泄漏”通常说的就是堆区。
    3、静态区(又称静态全局区)
    全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,所以静态区又分为两个段(data、bss后文详细解释)。程序结束后,由系统释放。
    4、代码区
    存放代码的区域
    5、文字常量区
    存放只读数据,如常量字符串

    所以变量所在内存区(下文还有变量所在段)如下:

    全局变量 -----> 静态区
    静态变量 -----> 静态区
    非静态局部变量、形参、返回值 -----> 栈区
    动态申请的变量 -----> 堆区
    代码 -----> 代码区
    常量字符串 -----> 文字常量区

    三、程序编译后的分段情况

    源文件在编译之后生成的.o文件已经将程序进行了分段,主要有以下四个段:
    1、代码段 .text
    text段是程序代码段,它是由编译器在编译连接时自动计算的,当你在链接定位文件中将该符号放置在代码段后,那么该符号表示的值就是代码段大小,编译连接时,该符号所代表的值会自动代入到源程序中。
    2、数据段(细分为两个段)
    ①已初始化段(又称全局初始化段、静态初始化段) .data
    data包含静态初始化的数据,所以有初值的全局变量和static变量在data区。段的起始位置也是由连接定位文件所确定,大小在编译连接时自动分配,它和你的程序大小没有关系,但和程序使用到的全局变量,常量数量相关。
    ②未初始化段(又称全局未初始化段、静态未初始化段) .bss
    通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0。bss段属于静态内存分配。它的初始值也是由用户自己定义的连接定位文件所确定,用户应该将它定义在可读写的ram区内,源程序中使用malloc分配的内存就是这一块,它不是根据data大小确定,主要由程序中同时分配内存最大值所确定,不过如果超出了范围,也就是分配失败,可以等空间释放之后再分配。
    3、只读数据段 .rodata
    程序中定义的常量字符串等
    4、堆栈段
    栈主要保存函数的局部变量和参数以及返回值。是一种“后进先出”(last in first out,lifo)的数据结构,在调用函数或过程后,系统通常会清除栈上保存的局部变量、函数调用信息及其它的信息。栈另外一个重要的特征是,它的地址空间“向下减少”,即当栈上保存的数据越多,栈的地址就越低
    堆保存函数内部动态分配内存,堆是“先进先出”(first in first out,fifo)数据结构。堆的地址空间“向上增加”,即当堆上保存的数据越多,堆的地址就越高。

    所以变量所在段的情况如下:

    未初始化全局变量 -----> 数据段—> 未初始化段 .bss
    未初始化静态变量 -----> 数据段—> 未初始化段 .bss
    初始化全局变量 -----> 数据段—> 初始化段 .data
    初始化静态变量 -----> 数据段—> 初始化段 .data
    代码 -----> 代码段
    常量字符串 -----> 只读数据段 .rodata
    非静态局部变量、形参、返回值 -----> 不存在,程序运行时才会在栈区产生
    动态申请的变量 -----> 不存在,程序运行时才会在堆区产生

    为了验证上述结果,我们写一下程序测试:

    #include <stdio.h>
    
    int a;
    int b = 1;
    static int c;
    static int d = 2;
    
    int main(int argc, char *argv[])
    {
    	  int e;
    	  int f = 3;
    	  static int g;
    	  static int h = 4;
    	  char i[] = "hello";
    	  //打印每个变量的值
    	  printf("a=%d\n",a);
    	  printf("b=%d\n",b);
    	  printf("c=%d\n",c);
    	  printf("d=%d\n",d);
    	  printf("e=%d\n",e);
    	  printf("f=%d\n",f);
    	  printf("g=%d\n",g);
    	  printf("h=%d\n",h);
    	  printf("i=%s\n",i);
    	  //打印每个变量的地址
    	  printf("a=%p\n",&a);
    	  printf("b=%p\n",&b);
    	  printf("c=%p\n",&c);
    	  printf("d=%p\n",&d);
    	  printf("e=%p\n",&e);
    	  printf("f=%p\n",&f);
    	  printf("g=%p\n",&g);
    	  printf("h=%p\n",&h);
    	  printf("i=%p\n",i);
      return 0;
    }
    

    编译(不链接,链接会产生更多的数据,不便验证):
    #gcc -c test.o test.c
    查看数据分段情况:
    #objdump -D test.o在这里插入图片描述

    编译链接并运行查看打印地址情况:
    #gcc -o test tset.c
    #./test
    在这里插入图片描述

    总结

    内存分区及数据段分配图
    在这里插入图片描述

    展开全文
  • C语言——操作系统内存分配过程

    千次阅读 2018-03-27 13:49:08
    某台计算机总的内存大小是128M,现在同时运行两个程序A和B,A需占用内存10M,B需占用内存100。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序A,接着再从内存中剩余的118M中划分出100M...

    内存分配机制的发展过程:

    第一阶段——程序直接操作物理内存。

    某台计算机总的内存大小是128M,现在同时运行两个程序A和B,A需占用内存10M,B需占用内存100。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序A,接着再从内存中剩余的118M中划分出100M分配给程序B

    1.进程地址空间不隔离。

    进程之间可以互相修改内存,导致不安全,可能会出现一个进程出现bug,导致另一个本来好好的进程挂掉。

    2.内存使用效率低。

    在A和B都运行的情况下,如果用户又运行了程序C,而程序C需要30M大小的内存才能运行,而此时系统只剩下18M的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间来供程序C使用,然后再将程序C的数据全部装入内存中运行。

    3.程序运行的地址不确定。

    当内存中的剩余空间可以满足程序C的要求后,操作系统会在剩余空间中随机分配一段连续的20M大小的空间给程序C使用,因为是随机分配的,所以程序运行的地址是不确定的。

    虚拟内存
    虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。目前,大多数操作系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。

    第二阶段——分段(解决了第一阶段的第1和第3个问题)

    在进程和物理内存增加一个中间层,利用一种间接的地址访问方法访问物理内存。程序中访问的内存地址不再是实际的物理内存地址,而是一个虚拟地址,然后由操作系统将这个虚拟地址映射到适当的物理内存地址上。这样,只要操作系统处理好虚拟地址到物理内存地址的映射,就可以保证不同的程序最终访问的内存地址位于不同的区域,彼此没有重叠,就可以达到内存地址空间隔离的效果。

    第三阶段——分页(解决了第一阶段的第2个问题)

    将地址空间分成许多的页。每页的大小由CPU决定,然后由操作系统选择页的大小。目前Inter系列的CPU支持4KB或4MB的页大小,而PC上目前都选择使用4KB。

    对比分段

    在分段的方法中,每次程序运行时总是把程序全部装入内存,而分页的方法则有所不同。分页的思想是程序运行时用到哪页就为哪页分配内存,没用到的页暂时保留在硬盘上。当用到这些页时再在物理地址空间中为这些页分配内存,然后建立虚拟地址空间中的页和刚分配的物理内存页间的映射。

    举例说明加载可执行文件的过程
    一个可执行文件(PE文件)其实就是一些编译链接好的数据和指令的集合,它也会被分成很多页,在PE文件执行的过程中,它往内存中装载的单位就是页。当一个PE文件被执行时,操作系统会先为该程序创建一个4GB的进程虚拟地址空间。前面介绍过,虚拟地址空间只是一个中间层而已,它的功能是利用一种映射机制将虚拟地址空间映射到物理地址空间,所以,创建4GB虚拟地址空间其实并不是要真的创建空间,只是要创建那种映射机制所需要的数据结构而已,这种数据结构就是页目和页表。

    .当创建完虚拟地址空间所需要的数据结构后,进程开始读取PE文件的第一页。在PE文件的第一页包含了PE文件头和段表等信息,进程根据文件头和段表等信息,将PE文件中所有的段一一映射到虚拟地址空间中相应的页(PE文件中的段的长度都是页长的整数倍)。这时PE文件的真正指令和数据还没有被装入内存中,操作系统只是根据PE文件的头部等信息建立了PE文件和进程虚拟地址空间中页的映射关系而已。当CPU要访问程序中用到的某个虚拟地址时,当CPU发现该地址并没有相相关联的物理地址时,CPU认为该虚拟地址所在的页面是个空页面,CPU会认为这是个页错误(Page Fault),CPU也就知道了操作系统还未给该PE页面分配内存,CPU会将控制权交还给操作系统。操作系统于是为该PE页面在物理空间中分配一个页面,然后再将这个物理页面与虚拟空间中的虚拟页面映射起来,然后将控制权再还给进程,进程从刚才发生页错误的位置重新开始执行。由于此时已为PE文件的那个页面分配了内存,所以就不会发生页错误了。随着程序的执行,页错误会不断地产生,操作系统也会为进程分配相应的物理页面来满足进程执行的需求。

    分页方法的核心思想就是当可执行文件执行到第x页时,就为第x页分配一个内存页y,然后再将这个内存页添加到进程虚拟地址空间的映射表中,这个映射表就相当于一个y=f(x)函数。应用程序通过这个映射表就可以访问到x页关联的y页了。

    内存管理

    最小存储单位是一个字节(1B),最小管理单位是一页(4KB),虚拟内存地址连续时物理内存地址可以不连续,即使一次分配6000字节(不到两页也分配两页),两个内存页物理地址可能不连续。多次申请内存时,如果之前分配的页内存没用完,则不再分配,除非之前分配的内存页用完才继续映射新的一页。硬盘也是如此(硬盘上称为Block块)。

    例如test文件里面只有4个字符,却也需要占4K的大小。
    这里写图片描述

    C语言中的malloc函数

    #include<stdio.h>
    #include<stdlib.h>
    int main(void){
    
        char * p = malloc(0);
    
        printf("%d,%d\n",*(p),*(p+32*4096));//打印第33页的内容,被默认初始化。
    
        free(p);
    }

    运行结果如下:
    这里写图片描述

    #include<stdio.h>
    #include<stdlib.h>
    int main(void){
    
        char * p = malloc(0);
    
        printf("%d,%d\n",*(p),*(p+33*4096));//打印第4页的内存位置,报段错误
    
        free(p);
    }

    运行结果如下:段错误是因为超过的虚拟内存地址并没有映射(分配)物理内存。
    这里写图片描述

    free函数

    malloc()给变量分配给变量内存时,除了数据区域外,还额外需要保存一些信息。底层有一个双向链表保存额外信息。malloc()给指针了12个字节,其中4个字节存放数据,另外8个存放其他信息或者空闲,如果将12个字节中前(低位)几个字节清空或者进行修改,free就可能出错,因为free只有首地址不能释放,还得需要额外附加信息(如malloc分配的长度)

    修改malloc申请的内存的指针位置,free会无法正常释放内存。
    这里写图片描述

    上图中的:
    这里写图片描述

    这里写图片描述

    此处又再次证明了malloc每一次分配的的内存页是33页。

    修改malloc申请的内存的指针的前几位的值,free也会无法正常释放内存。

    这里写图片描述

    参考文章https://blog.csdn.net/ljabclj/article/details/44155221

    展开全文
  • 一、进程进程空间: 1、什么是进程: ...程序运行起来就成为一个进程进程占用的空间就是进程空间。我们来看一下,进程空间是什么样的。 3、栈(Stack): 栈中可存放任意类型的变量,但必须是 aut...
  • 虚拟地址空间--用户进程看到的自己所占用内存 我们知道内核管理物理内存,其实除了管理本身内存外,还必须管理用户空间中进程内存,我们称这个内存进程地址空间,也就是系统中每个用户空间进程...
  • Linux 进程内存管理

    2014-02-19 23:04:01
     在c语言中,不同的数据类型占用的`空间是不同的,比如说一个char类型,占用的是一个字节长度,一个int 类型,一般占用的是4个字节(与系统有关)  对于多个字节的的数据存储,数据存储的顺序就显得比较重要的了,...
  • 最近项目中需要对程序的运行状态进行...如下示例可根据可执行文件名获得线程数、虚拟内存占用大小、物理内存占用大小、进程PID、CPU占用率和进程启动次数等信息。 1.程序源码 main.c #include <stdio.h>...
  • 首先,说一下我对内存泄露的理解,内存泄露是指:程序中一块不再使用的内存没有被释放,造成内存保持占用状态,使操作系统不能将内存分配给其它的程序(进程)。在C语言,用的最多的管理内存的函数莫过于malloc和...
  • Linux系统上的/proc目录是一种文件系统,即proc文件系统,与其它常见的文件系统不同的是,/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。...
  • 上网查,说内存泄漏指的就是分配的内存没有被释放,但是后面又解释说“”内存泄漏形象的比喻是"操作系统可提供给所有进程的存储空间正在被某个进程榨干",最终结果是程序运行时间越长,占用存储空间越来越多,最终...
  • C语言初始化

    2018-03-17 14:01:00
    比如核心初始化,和内存初始化栈:栈帧:一个进程中一般会有多个函数,每一个函数都需要在内存中开辟一个栈空间来使用,每一个函数所占用栈叫做栈帧。pclrspfp这四个数据。栈帧之空间的界定:fp(栈帧指针)指针用于...
  • 代码注入占用内存少并难以查找痕迹,在代码量小的时候比较合适。 不过这边有一个问题就是在执行用户选择的启动函数时我选择让目标进程使用CreateThread来调用dll的导出函数,这样做是否合适?测试了一些暂时还没发现...
  • 最近在研究JVM虚拟机内存占用情况,通过top命令看到进程的RES占用内存很大,已经超过了java虚拟机设置的大小,所以想弄明白top的RES的数据是怎么计算出来的,但是前提是需要将top的源码下载到本地进行研究。...
  • exit()函数与return语句的最大区别在于,调用exit()函数将会结束当前进程,同时删除子进程占用内存空间,把返回信息传给父进程。当exit()中的参数为0时,表示正常退出,其他返回值表示非正常退出,执行exit()...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    1.3 因为C语言没有精确定义类型的大小,所以我一般都用typedef定义int16和int32。然后根据实际的机器环境把它们定义为int、short、long等类型。这样看来,所有的问题都解决了,是吗? 1.4 新的64位机上的64位类型...
  • 1.形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。 2.实参可以是常量、变量、表达式、函数...
  • 难道在C语言中一个结构不能包含指向自己的指针吗? o 2.7 怎样建立和理解非常复杂的声明?例如定义一个包含 N 个指向返回指向字符的指针的函数的指针的数组? o 2.8 函数只定义了一次, 调用了一次, 但编译器提示...
  • 动态库(共享库) 动态库和静态库最大的不同就是,链接动态库并不需要将库...使用动态库占用内存空间小,即使修改了动态库中的代码,只要其相对地址不变,无需重新链接。 因为在执行过程中,需要计算被调用代码的.
  • 函数和变量在编译完成后会有实际的数据在那里,也就是运行时载入内存的时候会占用内存。现在先说变量。变量按其存储在内存中的位置分有3种, 全局/静态的, 局部/栈(stack)的,和堆(heap)变量。这3个概念其实牵扯...
  • C语言编写程序,用信号量和共享内存实现读写同步,程序中父进程为读进程,子进程为写...开启共享内存空间和二值信号量,子进程占用信号量,父进程无法执行读,等待子进程写完释放信号量后父进程进行读操作。依次类推。
  • 一、一个由C/C++编译到程序占用内存分为以下几个部分: 1、栈区(stack)——由编译器自动分配释放,在不需要的时候自动清除。用于存放函数的参数、局部变量等。操作方式类似数据结构中的栈(后进先出)。 2、堆...
  • 1. exit() 结束当前进程/... exit与return的区别exit()函数与return语句的最大区别在于,调用exit()函数将会结束当前进程,同时删除子进程占用内存空间,把返回信息传给父进程。当exit()中的参数为0时,表示正...
  • 进程并发度最大为10的计算机系统中,内存采用虚拟分页存储管理方式,页长为2KB,逻辑地址为32位,物理地址为24位,内存页框的分配和回收采用位示图法,页面置换采用LRU算法,请根据你所学到的知识,编程实现这个...

空空如也

空空如也

1 2 3 4 5 6
收藏数 117
精华内容 46
关键字:

c语言进程占用内存

c语言 订阅