【一天一个计算机知识】—— 【 C/C++ 内存管理与分布】

【一天一个计算机知识】—— 【 C/C++ 内存管理与分布】



⚡ CYBER_PROFILE ⚡
/// SYSTEM READY ///


[WARNING]: DETECTING HIGH ENERGY

🌊 🌉 🌊 心手合一 · 水到渠成

分隔符
>>> ACCESS TERMINAL <<<
[ 🦾 作者主页 ][ 🔥 C语言核心 ]
[ 💾 编程百度 ][ 📡 代码仓库 ]

---------------------------------------
Running Process: 100% | Latency: 0ms


索引与导读

🚩一、C/C++ 内存分布

我们先来看下面的一段代码和相关问题:

#include<stdio.h>#include<stdlib.h>// 【全局/静态区】.data:已初始化的全局变量int globalVar =1;// 【全局/静态区】.data:已初始化的静态全局变量(作用域限制在本文件)staticint staticGlobalVar =1;voidTest(){// 【全局/静态区】.data:已初始化的静态局部变量(生命周期为整个程序)staticint staticVar =1;// 【栈区】:局部变量,函数运行结束自动释放int localVar =1;// 【栈区】:局部数组int num1[10]={1,2,3,4};// 【栈区】:字符数组(注意:"abcd" 会被拷贝到栈上)char char2[]="abcd";// 【指针在栈区】,但指向的 "abcd" 字符串字面量在【常量区/代码段】constchar* pChar3 ="abcd";// 【指针在栈区】,指向【堆区】通过 malloc 分配的内存int* ptr1 =(int*)malloc(sizeof(int)*4);// 【指针在栈区】,指向【堆区】通过 calloc 分配并初始化的内存int* ptr2 =(int*)calloc(4,sizeof(int));// 【指针在栈区】,将 ptr2 原有的【堆区】内存进行扩充/移动int* ptr3 =(int*)realloc(ptr2,sizeof(int)*4);// 手动释放【堆区】内存free(ptr1);free(ptr3);}
在这里插入图片描述

在这里插入图片描述

🚩二、C语言的动态内存管理

🔗Lucy的空间骇客裂缝:C语言动态内存管理

💪C动态内存管理的面试考点

1)realloc的工作机制

voidTest(){int* p2 =(int*)calloc(4,sizeof(int));int* p3 =(int*)realloc(p2,sizeof(int)*10);free(p3 );}
  • 这里需要free(p2)
  • 不需要。 甚至绝对不能这样做
原因在于 realloc 的工作机制:如果 realloc 成功扩容,它会返回一个新的内存地址(可能是原地址,也可能是搬迁后的新地址)。如果返回了新地址,原内存块(p2)会自动被释放。如果你手动执行 free(p2),会导致“重复释放”(Double Free)的错误,这通常会引起程序崩溃

2)malloc/calloc/realloc的区别是什么?

函数功能描述初始化行为参数形式
malloc分配指定字节大小的内存。不初始化。内存里是随机的垃圾值。malloc(size_t size)
calloc分配 n 个元素的内存,并清零。自动初始化为 0calloc(n, size)
realloc调整已分配内存块的大小。不对新增空间进行初始化。realloc(ptr, new_size)

🚩三、C++ 动态内存管理

  • C语言内存管理方式在C++中可以继续使用
  • C++又提出了自己的内存管理方式:通过newdelete操作符进行动态内存管理

1)操作内置类型

C++中,内置类型(如 int, double, char 等)的动态内存分配主要通过 newdelete 运算符来实现

1.1)单个变量的分配和释放

  • 分配:new 类型 或 new 类型(初始值)
  • 释放:delete 指针变量
intmain(){// 1. 分配一个未初始化的 intint* p1 =newint;// 2. 分配并初始化为 100int* p2 =newint(100);// 使用完毕后必须释放内存delete p1;delete p2;// 良好的习惯:将指针置为空,防止野指针 p1 =nullptr; p2 =nullptr;return0;}

1.2)一维数组的分配与释放

处理数组时,需要使用方括号 []

  • 分配:new 类型[元素个数]
  • 释放:delete[] 指针变量 (注意:释放数组必须加 [],否则会导致未定义行为或内存泄漏)
voidmanageArray(){int size =5;// 分配一个长度为 5 的 int 数组int* arr =newint[size];// 初始化数组(C++11 之后也可以使用 new int[5]{1, 2, 3, 4, 5})for(int i =0; i < size;++i){ arr[i]= i *10;}// 释放数组内存delete[] arr;}

2)操作自定义类型

对于自定义类型(如 structclass),C++newdelete 不仅仅是分配内存,它们还负责调用构造函数和析构函数

  • 最核心的差异在于:自定义类型的生命周期管理包含了初始化(调用构造函数)清理(调用析构函数) 的过程
#include<iostream>usingnamespace std;classA{public:A(int a =0):_a(a){ cout <<"A():"<<this<< endl;}~A(){ cout <<"~A():"<<this<< endl;}private:int _a;};intmain(){ A* p1 =(A*)operatornew(sizeof(A)); A* p2 =newA(1);operatordelete(p1);delete p2;int* p3 =(int*)operatornew(sizeof(int));int* p4 =newint;operatordelete(p3);delete p4; A* p5 =(A*)operatornew(sizeof(A)*10); A* p6 =new A[10];operatordelete[](p5);delete[] p6;return0;}

3)operator new与operator delete函数

  • newdelete 是用户进行动态内存申请和释放的操作符,operator newoperator delete 是系统提供的全局函数
  • new 在底层调用 operator new 全局函数来申请空间,delete 在底层通过 operator delete 全局函数来释放空间

  • new 表达式 (new expression): 这是我们在代码中常用的 Type* p = new Type();。它是一个“全自动”过程,做了两件事:
    1. 调用 operator new 分配原始内存。
    2. 调用构造函数初始化对象。
  • operator new (函数): 这是一个类似于 malloc 的函数,它的唯一任务是分配一块指定大小的原始内存,不负责构造对象。

3.1)operator new详解

🔗Lucy的空间骇客裂缝:operator new官方解析
  • 原型:
void*operatornew(size_t size);
  • 工作原理
    • 参数: size 是需要分配的字节数(编译器会自动计算对象大小并传入)。
    • 返回值: 返回指向分配的内存起始地址的 void* 指针。
    • 失败处理: 默认情况下,如果分配失败,它不会返回 nullptr,而是抛出 std::bad_alloc 异常。
    • 自定义行为: 你可以重载全局或类特定的 operator new 来实现自己的内存池或审计逻辑

3.2)operator delete 详解

🔗Lucy的空间骇客裂缝:operator delete官方解析
  • 原型:
voidoperatordelete(void* ptr)noexcept;
  • 工作原理
    • 对应关系delete 表达式会先调用对象的析构函数,然后调用 operator delete 来释放内存。
    • 安全性:根据 C++ 标准,向 operator delete 传递 nullptr 是安全的,函数会直接返回而不执行任何操作。
    • 释放逻辑:在底层,它通常封装了 free() 或者系统底层的内存回收接口。
C++ 中,noexcept 是一个异常说明,它告诉编译器和程序员:这个函数保证不会抛出异常

通过上述两个全局函数的实现知道,operator new 实际也是通过 malloc 来申请空间,如果 malloc 申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过 free 来释放空间的


4)new和delete的实现原理

4.1)内置类型

如果申请的是内置类型的空间,newmallocdeletefree 基本类似,不同的地方是:
new/delete 申请和释放的是单个元素的空间,new[]delete[] 申请的是连续空间,而且 new 在申请空间失败时会抛异常,malloc 会返回 NULL


4.2)自定义类型

  • new 的原理
    1. 调用 operator new 函数申请空间
    2. 在申请的空间上执行构造函数,完成对象的构造
  • delete 的原理
    1. 在空间上执行析构函数,完成对象中资源的清理工作
    2. 调用 operator delete 函数释放对象的空间
  • new T[N] 的原理
    1. 调用 operator new[] 函数,在 operator new[] 中实际调用 operator new 函数完成 N 个对象空间的申请
    2. 在申请的空间上执行 N 次构造函数
  • delete[] 的原理
    1. 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理
    2. 调用 operator delete[] 释放空间,实际在 operator delete[] 中调用 operator delete 来释放空间

5)malloc/free和new/delete的区别

malloc/freenew/delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:

  1. mallocfree 是函数,newdelete 是操作符
  2. malloc 申请的空间不会初始化,new 可以初始化
  3. malloc 申请空间时,需要手动计算空间大小并传递,new 只需在其后跟上空间的类型即可,如果是多个对象,[] 中指定对象个数即可
  4. malloc 的返回值为 void*,在使用时必须强转,new 不需要,因为 new 后跟的是空间的类型
  5. malloc 申请空间失败时,返回的是 NULL,因此使用时必须判空,new 不需要,但是 new 需要捕获异常
  6. 申请自定义类型对象时,malloc/free 只会开辟空间,不会调用构造函数与析构函数,而 new 在申请空间后会调用构造函数完成对象的初始化,delete 在释放空间前会调用析构函数完成空间中资源的清理释放

💻结尾— 核心连接协议

警告:🌠🌠正在接入底层技术矩阵。如果你已成功破解学习中的逻辑断层,请执行以下指令序列以同步数据:🌠🌠


【📡】 建立深度链接:关注本终端。在赛博丛林中深耕底层架构,从原始代码到进阶协议,同步见证每一次系统升级。

【⚡】 能量过载分发:执行点赞操作。通过高带宽分发,让优质模组在信息流中高亮显示,赋予知识跨维度的传播力。

【💾】 离线缓存核心:将本页加入收藏。把这些高频实战逻辑存入你的离线存储器,在遭遇系统崩溃或需要离线检索时,实现瞬时读取。

【💬】 协议加密解密:评论区留下你的散列码。分享你曾遭遇的代码冲突或系统漏洞(那些年踩过的坑),通过交互式编译共同绕过技术陷阱。

【🛰️】 信号频率投票:通过投票发射你的选择。你的每一次点击都在重新定义矩阵的进化方向,决定下一个被全量拆解的技术节点。


在这里插入图片描述

Read more

Python实现 MCP 客户端调用(高德地图 MCP 服务)查询天气示例

Python实现 MCP 客户端调用(高德地图 MCP 服务)查询天气示例

文章目录 * MCP 官网 * MCP 官方文档中文版 * 官方 MCP 服务示例 * Github * MCP 市场 * 简介 * 架构 * 高德地图 MCP 客户端示例 * python-sdk 客户端 * java-sdk 客户端 MCP 官网 * https://modelcontextprotocol.io/introduction MCP 官方文档中文版 * https://app.apifox.com/project/5991953 官方 MCP 服务示例 * https://github.com/modelcontextprotocol/servers Github * python-sdk:https://github.com/modelcontextprotocol/python-sdk * java-sdk:

By Ne0inhk
43-dify案例分享-MCP-Server让工作流秒变第三方可调用服务

43-dify案例分享-MCP-Server让工作流秒变第三方可调用服务

1.前言 之前我们为大家介绍过MCP SSE插件,它能够支持MCP-server在Dify平台上的调用,从而帮助Dify与第三方平台提供的MCP-server进行无缝对接。有些小伙伴提出了疑问:既然Dify可以通过MCP SSE插件调用其他平台的MCP-server,那么Dify的工作流或Chatflow是否也能发布为MCP-server,供其他支持MCP client的工具使用呢?今天,我们将为大家介绍一款Dify插件——mcp-server,它能够实现这一功能,即将Dify的工作流或Chatflow发布为MCP-server,供其他第三方工具调用。 插件名字叫做MCP-server,我们在dify插件市场可以找到这个工具 Mcp-server 是一个由 Dify 社区贡献的 Extension 类型插件。安装后,你可以把任何 Dify 应用转变成符合 MCP 标准的 Server Endpoint,供外部 MCP 客户端直接访问。它的主要功能包括: * **暴露为 MCP 工具:**将 Dify 应用抽象为单一 MCP 工具,供外部 MCP 客户端(如

By Ne0inhk
【MCP】详细了解MCP协议:和function call的区别何在?如何使用MCP?

【MCP】详细了解MCP协议:和function call的区别何在?如何使用MCP?

本文介绍了MCP大模型上下文协议的的概念,并对比了MCP协议和function call的区别,同时用python sdk为例介绍了mcp的使用方式。 1. 什么是MCP? 官网:https://modelcontextprotocol.io/introduction 2025年,Anthropic提出了MCP协议。MCP全称为Model Context Protocol,翻译过来是大模型上下文协议。这个协议的主要为AI大模型和外部工具(比如让AI去查询信息,或者让AI操作本地文件)之间的交互提供了一个统一的处理协议。我们常用的USB TypeC接口(USB-C)统一了USB接口的样式,MCP协议就好比AI大模型中的USB-C,统一了大模型与工具的对接方式。 MCP协议采用了C/S架构,也就是服务端、客户端架构,能支持在客户端设备上调用远程Server提供的服务,同时也支持stdio流式传输模式,也就是在客户端本地启动mcp服务端。只需要在配置文件中新增MCP服务端,就能用上这个MCP服务器提供的各种工具,大大提高了大模型使用外部工具的便捷性。 MCP是开源协议,能让所有A

By Ne0inhk