c/c++内存机制

利用arpspoof + sslStrip尝试进行arp欺骗 阅读详情

一:C语言中的内存机制

在C语言中,内存主要分为如下5个存储区:

(1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。

(2)堆(Heap):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片内存会由OS回收。

(3)全局区/静态区(Global Static Area): 全局变量和静态变量存放区,程序一经编译好,该区域便存在。并且在C语言中初始化的全局变量和静态变量和未初始化的放在相邻的两个区域(在C++中,由于全局变量和静态变量编译器会给这些变量自动初始化赋值,所以没有区分了)。由于全局变量一直占据内存空间且不易维护,推荐少用。程序结束时释放。

(4)C风格字符串常量存储区: 专门存放字符串常量的地方,程序结束时释放。

(5)程序代码区:存放程序二进制代码的区域。


二:C++中的内存机制

在C++语言中,与C类似,不过也有所不同,内存主要分为如下5个存储区:

(1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。

(2)堆(Heap):这里与C不同的是,该堆是由new申请的内存,由delete或delete[]负责释放

(3)自由存储区(Free Storage):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片内存会由OS回收。

(4)全局区/静态区(Global Static Area): 全局变量和静态变量存放区,程序一经编译好,该区域便存在。在C++中,由于全局变量和静态变量编译器会给这些变量自动初始化赋值,所以没有区分了初始化变量和未初始化变量了。由于全局变量一直占据内存空间且不易维护,推荐少用。程序结束时释放。

(5)常量存储区: 这是一块比较特殊的存储区,专门存储不能修改的常量(如果采用非正常手段更改当然也是可以的了)。


三:堆和栈的区别

3.1 栈(Stack)

    具体的讲,现代计算机(冯诺依曼串行执行机制),都直接在代码低层支持栈的数据结构。这体现在有专门的寄存器指向栈所在的地址(SS,堆栈段寄存器,存放堆栈段地址);有专门的机器指令完成数据入栈出栈的操作(汇编中有PUSH和POP指令)。

    这种机制的特点是效率高,但支持数据的数据有限,一般是整数、指针、浮点数等系统直接支持的数据类型,并不直接支持其他的数据结构(可以自定义栈结构支持多种数据类型)。因为栈的这种特点,对栈的使用在程序中是非常频繁的 。对子程序的调用就是直接利用栈完成的。机器的call指令里隐含了把返回地址入栈,然后跳转至子程序地址的操作,而子程序的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作。

    C/C++中的函数自动变量就是直接使用栈的例子,这也就是为什么当函数返回时,该函数的自动变量自动失效的原因,因而要避免返回栈内存和栈引用,以免内存泄露。

3.2 堆(Heap)

    和栈不同的是,堆得数据结构并不是由系统(无论是机器硬件系统还是操作系统)支持的,而是由函数库提供的。基本的malloc/calloc/realloc/free函数维护了一套内部的堆数据结构(在C++中则增加了new/delete维护)。

    当程序用这些函数去获得新的内存空间时,这套函数首先试图从内部堆中寻找可用的内存空间(常见内存分配算法有:首次适应算法、循环首次适应算法、最佳适应算法和最差适应算法等。os的基本内容!!)。如果没有可用的内存空间,则试图利用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部堆中去,然后再以适当的形式返回给调用者。当程序释放分配的内存空间时,这片内存空间被返回到内部堆结构中,可能会被适当的处理(比如空闲空间合并成更大的空闲空间),以更适合下一次内存分配申请。 这套复杂的分配机制实际上相当于一个内存分配的缓冲池(Cache),使用这套机制有如下几个原因:

(1)系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配);这样的话对于大量的小内存分配来说会造成浪费。

(2)系统调用申请内存可能是代价昂贵的。 系统调用可能涉及到用户态和核心态的转换。

(3)没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。

3.3 栈和堆的对比

从以上介绍中,它们有如下区别:

(1)栈是系统提供的功能,特点是快速高效,缺点是由限制,数据不灵活;

       堆是函数库提供的功能,特点是灵活方便,数据适应面广,但是效率有一定降低。

(2)栈是系统数据结构,对于进程/线程是唯一的;

       堆是函数库内部数据结构,不一定唯一,不同堆分配的内存无法互相操作。

(3)栈空间分静态分配和动态分配,一般由编译器完成静态分配,自动释放,栈的动态分配是不被鼓励的;

       堆得分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/释放内存匹配是良好程序的基本要素。

(4)碎片问题

    对于堆来讲,频繁的new/delete等操作势必会造成内存空间的不连续,从而造成大量的碎片,使程序的效率降低;对于栈来讲,则不会存在这个问题,因为栈是后进先出(LIFO)的队列。

(5)生长方向

    堆的生长方向是向上的,也就是向这内存地址增加的方向;对于栈来讲,生长方向却是向下的,是向着内存地址减少的方向增长。

(6)分配方式

      堆都是动态分配的,没有静态分配的堆;

      栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配则由alloca函数进行分配,但是栈的动态分配和堆不同,它的动态分配是由编译器进行释放,无需我们手工实现。

(7)分配效率

      栈是机器系统提供的数据结构,计算机在底层提供支持,分配有专门的堆栈段寄存器,入栈出栈有专门的机器指令,这些都决定了栈的高效率执行。

      堆是由C/C++函数库提供的,机制比较复杂,有不同的分配算法,易产生内存碎片,需要对内存进行各种管理,效率比栈要低很多。


四:具体实例分析

例子(一)

看下面的一小段C程序,仔细体会各种内存分配机制。

 
int a = 0; //全局初始化区,a的值为0
char *p1;  //全局未初始化区(C++中则初始化为NULL) 
int main()   
{   
     int b;                  //b分配在栈上,整型  
     char s[] = "abc";       //s分配在栈上,char *类型;"abc\0"分配在栈上,运行时赋值,函数结束销毁 
     char *p2;               //p2分配在栈上,未初始化   
     char *p3 = "123456";    //p3指向"123456"分配在字符串常量存储区的地址,编译时确定 
     static int c = 0;       //c在全局(静态)初始化区,可以多次跨函数调用而保持原值   
     p1 = (char *)malloc(10); //p1在全局未初始化区,指向分配得来得10字节的堆区地址   
     p2 = (char *)malloc(20); //p2指向分配得来得20字节的堆区地址  
     strcpy(p1, "123456");    //"123456"放在字符串常量存储区,编译器可能会将它与p3所指向的"123456"优化成一块 
     return 0; 
 } 

例子(二)

看下面的一小段代码,体会堆与栈的区别:

int foo() 
{ 
    //其余代码    
    int *p = new int[5]; 
    //其余代码
    return 0;
}

    其中的语句int *p = new int[5];就包含了堆与栈。其中new关键字分配了一块堆内存,而指针p本身所占得内存为栈内存(一般4个字节表示地址)。这句话的意思是在栈内存中存放了一个指向一块堆内存的指针p。在程序中先确定在堆中分配内存的大小,然后调用new关键字分配内存,最后返回这块内存首址,放入栈中。汇编代码为:

int foo()
{
008C1520  push        ebp  
008C1521  mov         ebp,esp  
008C1523  sub         esp,0D8h  
008C1529  push        ebx  
008C152A  push        esi  
008C152B  push        edi  
008C152C  lea         edi,[ebp-0D8h]  
008C1532  mov         ecx,36h  
008C1537  mov         eax,0CCCCCCCCh  
008C153C  rep stos    dword ptr es:[edi]  
    int *p = new int[5];
008C153E  push        14h  
008C1540  call        operator new[] (8C1258h)  
008C1545  add         esp,4  
008C1548  mov         dword ptr [ebp-0D4h],eax  
008C154E  mov         eax,dword ptr [ebp-0D4h]  
008C1554  mov         dword ptr [p],eax  
 
    return 0;
008C1557  xor         eax,eax  
}
008C1559  pop         edi  
008C155A  pop         esi  
008C155B  pop         ebx  
008C155C  add         esp,0D8h  
008C1562  cmp         ebp,esp  
008C1564  call        @ILT+395(__RTC_CheckEsp) (8C1190h)  
008C1569  mov         esp,ebp  
008C156B  pop         ebp  
008C156C  ret  

    如果需要释放内存,这里我们需要使用delete[] p,告诉编译器,我要删除的是一个数组。

例子(三)

看下面的一小段代码,试着找出其中的错误:

#include <iostream> 
using namespace std; 
int main() 
{ 
    char a[] = "Hello"; // 分配在栈上
    a[0] = 'X'; 
    cout << a << endl; 
    char *p = "World";  // 分配在字符串常量存储区的地址
    p[0] = 'X'; 
    cout << p << endl;  
    return 0; 
}

    发现问题了吗?是的,字符数组a的容量是6个字符,其内容为"hello\0"。a的内容时可以改变的,比如a[0]='X',因为其是在栈上分配的,也就是在运行时确定的内容。但是指针p指向的字符串"world"分配在字符串常量存储区,内容为"world\0",常量字符串的内容时不可以修改的。从语法上来说,编译器并不觉得语句p[0]='X'有什么问题,但是在运行时则会出现"access violation"非法内存访问的问题。

以下几个函数的变化要看清楚了:吐舌笑脸

char *GetString1(void) 
{ 
    char p[] = "hello,world"; //结果:h。由于数组指针指向第一元素的地址,所以调用之后是h 
    return p; 
} 
char *GetString2(void) 
{ 
    char *p = "hello,world"; //结果:hello,world。由于p指向“hello,world”字符串常量区域地址 
    return p; 
} 
char *GetString3(void) 
{ 
    char *p = (char *)malloc(20); // 指向p所分配的堆上的内存空间。
    return p; 
} 
char *GetString4(void) 
{ 
    char *p = new char[20]; // 指向p所分配的内存空间,p本身在栈上的,p所指向的空间是堆上的。
    return p; 
}

附录:内存管理注意事项太阳

【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL,防止使用指针值为NULL的内存,可以在函数入口处断言检测。

【规则2】不要忘记为数组或动态内存赋初值(比如calloc比malloc就要好),指针初始化为NULL(c++中为0)。

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

【规则4】动态内存的申请和释放必须配对,防止内存泄露,具体为malloc/calloc/realloc和free配对,new和delete以及delete[]配对。

【规则5】用free或者delete释放内存后,应立即将指针设置为NULL(C++中为0),防止产生“野指针”、"悬垂指针"。

【规则6】遇到不懂得问题及时debug,一般的虫子灯泡debug一下就灰飞烟灭了,一切bug都是浮云而已。

安装keil5(MDK)及导入pack包教程 首先说明的是我安装的Keil版本为Keil V5.29.0.0 1、安装软件 右键管理员权限运行安装包 设置安装路径以及pack的存放路径 随意输入First Name和E-mail 安装驱动 完成软件安装,然后可以先关闭弹出的Pack Install(一会再添加) 2、激活一下软件 打开桌面的Keil File → License Management(我之前注册过了) 右... 阅读详情

相关推荐

异步fifo的UVM验证(最终最终版)

更新了refmdl以及scb

qq_44674008的博客 2988

C++内存空间管理

1.C++内存机制 1.栈(Stack),函数中的局部变量,由编译器负责分配释放,函数结束,变量释放。 2.堆(Heap),通过new 申请的内存,由delete或delete[]释放 3.自由存储区(Free Storage),由程序员用malloc,calloc/realloc分配,free进行释放,忘记free,会导致内存泄漏,程序结束时,该区域内存由OS回收 4.全局区/静态区(Global Static Area),全局变量和静态变量存储区。程序编译完成后,该区域便存在,在C++中,由于全

u011555996的博客 7286

I2S时序及音频驱动

I2S、音频驱动

qq_41882586的博客 3948

C++内存管理机制

内存五大分区 1.栈区 程序运行时分配内存。 c++程序运行时分配内存,主要存储函数的参数以及局部变量。 局部变量分配内存时在栈区从高地址到低地址查找空的内存区域进行分配。 函数运行结束时回收内存。 2.堆区 程序运行时分配内存 堆区又称动态内存分配区,主要存储new或者malloc出来的内存,分配内存时在内存的堆区中从低地址到高地址寻找空的内存区域进行分配。 delete或者free后回收内存,如果没有delete或者free操作则在程序运行结束后由操作系统回收内存。 3.全局区 程序编译时分配内存 全

weixin_45800628的博客 4534

UE 顶点动画工具 (VAT)

导入模型需要勾选全精度UV。

iesoxj的博客 1643

(一)利用Python实现数据集读取,Python基本文件操作介绍

机器学习是计算机对大量数据的分析过程,在机器学习的实际项目中,通常都需要准备数据集,数据集通常包含的数据数量是庞大的。例如,在处理计算机视觉领域的项目时,每一张图片都是一个单独的文件,为了提高模型训练的效果,图片数量通常会比较多,因此需要合理且高效的操作将所有的图片数据读取。本篇旨在介绍如何用Python对海量文件进行遍历,也是机器学习实践的第一步。.........

ZZR2631574030的博客 6357

[C++] C++中的内存管理机制

目录1. C/C++的内存分布 1. C/C++的内存分布

weixin_43717520的博客 1532

台达PLC DIAdesigner-AX 编程实战:从安装到通信配置

本文详细介绍了台达PLC DIAdesigner-AX编程的实战操作,从软件安装、项目创建到通信配置的全流程。重点讲解了TCP/IP通信设置、库文件管理及常见错误处理,帮助工程师快速掌握台达PLC编程技巧,提升工业自动化项目的开发效率。

weixin_29215391的博客 530

C++内存管理--详谈

1、简述 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不在,内存泄漏几乎在每个C++程序中都会发生,因此要想成为C++高手,内存管理一关是必须要过的,除非放弃C++,转到Java或者.NET,他们的内存管理基本是自动的,当然你也放弃了自由和对内存的支配权,还放弃了C++超绝的性能。本期专题将从内存管理、内存泄漏、内存回收这三个方面来探讨C++内存管理问题。 ..

locahuang的博客 2369

基于Python的IMF经济数据爬取与分析:从入门到实战

本文详细介绍了如何使用Python爬取国际货币基金组织(IMF)的经济数据,包括最新的爬虫技术、反反爬策略、数据解析与存储方法。文章从IMF数据源分析开始,逐步讲解如何构建一个完整的爬虫系统,并提供了详细的代码实现和优化建议。通过本文,读者将掌握爬取复杂国际组织数据的关键技术,并能将这些技术应用于其他类似的数据获取场景。关键词:Python爬虫、IMF数据、经济数据获取、数据清洗、反爬策略IMF Data (data.imf.org) - 主要数据门户。

2201_76125261的博客 1439

[UVM]UVM TLM2.0简介及应用实例分析

本文介绍了TLM2.0在UVM中的实现与应用。TLM2.0作为SystemC模型间的核心传输机制,相比TLM1.0提供了更丰富的特性,包括双向阻塞/非阻塞接口、时间标记和统一数据包。文章详细解析了TLM2.0在UVM中的接口实现方式,包括socket类型定义、数据传输机制以及时间标记处理。通过一个具体实例,展示了如何在UVM组件中使用TLM2.0的initiator和target socket进行数据传输,并说明了标准数据包格式和精确时间标记的优势。最后指出TLM2.0在UVM中的实现主要是为了与Syste

元直的博客 5398

【C++】C/C++内存管理

本文总共写了7000字,从C/C++内存分布、C语言中内存管理方式、等6个方面,去系统地带大家一起探索C/C++内存管理方式,也了解到了内存泄漏的危害以及如何防止内存泄漏,希望大家读后能够有所收获!

qq_62662919的博客 4138

影楼精修-肤色统一算法解析

本文介绍了影楼精修中肤色统一算法的实现方案,并以像素蛋糕软件为例进行详细分析。肤色统一旨在通过调整人像照片中皮肤区域的颜色,使其看起来更加均匀一致。像素蛋糕软件提供了AI肤色统一和传统肤色统一两种功能,分别适用于不同需求。传统肤色统一算法通过皮肤分割、人脸检测、亮度统一和颜色统一等步骤,实现了对皮肤区域的精细调整。文章还提供了亮度统一的核心代码,并对比了传统算法与AI算法的效果,指出AI算法在自然度和亮度矫正方面表现更优。整体而言,本文为影楼精修中的肤色统一提供了实用的技术参考。

Trent1985的专栏 2068

C++冲刺(五)C/C++内存机制

(一)C内存机制 1. 栈(Stack):         位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。 2. 堆(Heap) :         由程序员用malloc()/calloc()/realloc()分配空间,free()释放所申请的空间。如果程序员忘记free(),则会造成内存泄漏,程序结束时可能会由操作系统回收,也许就一直占用着直至

LinEvan 930

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C/C++的内存机制

C/C++的内存机制 一:C语言中的内存机制 在C语言中,内存主要分为如下5个存储区: (1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。 (2)堆(Heap):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片...

weixin_34249367的博客 202

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

c/c++内存机制(转)

c/c++内存机制(一)(转) 一:C语言中的内存机制 在C语言中,内存主要分为如下5个存储区: (1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。 (2)堆(Heap):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片内存会由OS回收。 ...

weixin_33924220的博客 95

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C/C++内存分配机制

C/C++内存分配机制 1.C语言中的内存机制 在C语言中,内存主要分为如下5个存储区: (1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。 (2)堆(Heap):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片内存会由OS回

Thanksgiveing的专栏 538

【c/c++】深入探秘:C++内存管理的机制

return 0;new/delete和最大区别是new/delete对于【自定义类型】除了开空间,还会调用构造函数和析构函数new过程跳转到构造函数delete调用析构函数operator new,接下来我们来讲解这一部分。

Quietcoder的博客 5124

C/C++语言特性(内存管理、指针操作、编译链接机制)

掌握C/C++语言特性(内存管理、指针操作、编译链接机制),熟悉面向对象编程(封装/继承/多态)

Chihiro1002的博客 798

c/c++内存分配机制

1.C语言中的内存机制 在C语言中,内存主要分为如下5个存储区: (1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。 (2)堆(Heap):由程序员用malloc/calloc/realloc分配,free释放。如果程序员忘记free了,则会造成内存泄露,程序结束时该片内存会由OS回收,但程序只要不结束,就有可能造成内存泄露。 (3)...

常胜将军的博客 462

c/c++内存机制(一)(原)

博问闪存首页新随笔联系管理 随笔- 72  文章- 8  评论- 78  c/c++内存机制(一)(原) 一:C语言中的内存机制 在C语言中,内存主要分为如下5个存储区: (1)栈(Stack):位于函数内的局部变量(包括函数实参),由编译器负责分配释放,函数结束,栈变量失效。 (2)堆(Heap):由程序员用malloc/calloc/

jfkidear的专栏 1042
上一篇: c++ 编译期与运行期 总结
下一篇: 变量的生命周期与作用域
cjbbx
博客等级 码龄16年 12粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值