小工具知识网

当前位置: 首页 > 行业知识 > 『C++成长记』内存管理

行业知识

『C++成长记』内存管理

2026-11-02 22:12:14 来源:互联网转载

博客主页:小���又困了

系列专栏:C++

人之为学,不日近则日退

❤️感谢大家点赞收藏⭐评论✍️

目录

一、C/C++内存分布

二、内存管理方式

2.1C语言内存管理方式 

2.2C++内存管理方式 

2.2.1new/delete操作内置类型

2.2.1new和delete操作自定义类型

三、operator new与operator delete函数

四、new和delete的实现原理

4.1内置类型

4.2自定义类型

五、定位new表达式(placement-new)

5.1概念

5.2使用格式

5.3使用场景

六、malloc/free和new/delete的区别

 七、内存泄漏

7.1什么是内存泄漏

7.2内存泄漏的危害

7.3内存泄漏分类

7.4检测内存泄漏

7.5避免内存泄漏


一、C/C++内存分布

    在C和C++中,内存分布主要包括以下几个部分:

代码段(Code Segment):

  • 包含程序的机器代码,也称为文本段。
  • 是只读的,存储程序的执行代码。
  • 在程序运行时不可修改。

    数据段(Data Segment):

    • 包括初始化的全局变量和静态变量。
    • 在程序开始运行时分配,并在整个程序的执行周期内保持不变。
    • 数据区(Data Section): 存储已经初始化的全局变量和静态变量。
    • BSS段(Block Started by Symbol): 存储未初始化的全局变量和静态变量。

      堆(Heap):

      • 由程序员分配和释放的内存区域。
      • 动态分配的内存(例如使用new和malloc函数)存储在这里。
      • 堆的大小在程序运行时可以动态调整。

        栈(Stack):

        • 存储函数的局部变量和函数调用的上下文信息。
        • 由编译器自动分配和释放。
        • 栈的大小在程序运行时是固定的。

          堆栈区域之间的空间(Heap-Stack Gap):

          • 用于防止堆和栈之间的冲突。
          • 可以防止堆溢出覆盖栈数据或栈溢出覆盖堆数据。

             小Tips:这些区域在内存中的布局可能因操作系统和编译器而异,但通常遵循相似的结构。在运行时,栈的地址通常位于较高的内存地址,而堆的地址通常位于较低的内存地址。代码段和数据段的位置取决于可执行文件的加载方式,通常在较高的内存地址。 

            二、内存管理方式

            2.1C语言内存管理方式 

                C语言提供了一些基本的内存管理函数和操作符,使程序能够有效地分配和释放内存。以下是C语言中常用的内存管理方式:

            malloc() 和 free():

            • malloc()函数用于动态分配指定大小的内存空间。
            • free()函数用于释放先前由malloc()分配的内存空间。
            • 例子:
              // 分配10个整数大小的内存空间int *ptr = (int *)malloc(10 * sizeof(int));if (ptr != NULL) {    // 使用内存    // ...    // 释放内存    free(ptr);}

               calloc() 和 realloc():

              • calloc()函数用于分配指定数量和大小的内存空间,并将其初始化为零。
              • realloc()函数用于更改之前分配的内存块的大小。
              • 例子:
                // 分配并初始化为0,10个整数大小的内存空间int *ptr = (int *)calloc(10, sizeof(int));if (ptr != NULL){    // 使用内存    // ...    // 重新分配内存空间为20个整数大小    ptr = (int *)realloc(ptr, 20 * sizeof(int));    // 使用重新分配后的内存    // ...    // 释放内存    free(ptr);}

                静态分配:

                • 静态分配是在编译时为变量分配内存空间。
                • 包括全局变量、静态变量和局部变量(在函数外部定义的变量是静态的)。
                • 内存分配和释放由编译器自动处理。

                  自动变量:

                  • 在函数内部定义的变量通常是自动变量。
                  • 自动变量的内存分配和释放由程序的执行控制流决定。

                    指针和动态内存分配:

                    • 使用指针进行内存分配和释放是C语言中动态内存管理的重要部分。
                    • 必须小心管理分配的内存,以避免内存泄漏和悬空指针问题。

                       小Tips:C语言中的内存管理是相对低级的,程序员需要手动分配和释放内存。不正确的内存管理可能导致内存泄漏、悬空指针或者堆栈溢出等问题。因此,编写健壮和高效的代码需要仔细管理内存的分配和释放。

                      2.2C++内存管理方式 

                          C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

                      2.2.1new/delete操作内置类型

                      void Test(){  // 动态申请一个int类型的空间  int* ptr1 = new int;    // 动态申请一个int类型的空间并初始化为10  int* ptr2 = new int(10);    // 动态申请10个int类型的空间,不初始化  int* ptr3 = new int[10];  // 动态申请10个int类型的空间,并初始化前三个  int* ptr4 = new int[10]{1,2,3};  delete ptr1;  delete ptr2;  delete[] ptr3;  delete[] ptr4;}

                      小Tips:用new开辟空间是不会进行初始化的。如果我们想动态申请并初始化,类型后面要跟圆括号 () ,动态申请多个连续空间,类型后面跟的是方括号 [ ] ,如果要对这多个连续的空间初始化,可以在 [ ] 的后面跟 { } , { } 里面是初始化的数据,初始化的值不够,后面会默认初始化为0。申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[ ]和delete[ ]。

                      2.2.1new和delete操作自定义类型

                      class A{public:    A(int a = 0)        : _a(a)    {        cout 

上一篇:app怎么上传到服务器失败?

下一篇:chrome插件webRequest拦截请求并获取post请求体requestBody数据raw内容,解决中文乱码问题