当前位置: 首页 > article >正文

Swift与iOS内存管理机制深度剖析

前言

内存管理是每一位 iOS 开发者都绕不开的话题。虽然 Swift 的 ARC(自动引用计数)极大简化了开发者的工作,但只有深入理解其底层实现,才能写出高效、健壮的代码,避免各种隐蔽的内存问题。本文将从底层原理出发,系统梳理 Swift 与 iOS 的内存管理机制,结合实战经验,分享常见问题与优化建议。

一、ARC 的底层实现原理

1.1 ARC 的本质与设计目标

ARC(Automatic Reference Counting,自动引用计数)并非传统意义上的垃圾回收器(如 Java 的 GC),而是一种编译器驱动的内存管理机制。其核心设计目标包括:

  • 自动管理对象生命周期,有效防止内存泄漏和野指针问题;
  • 高性能,最大限度减少运行时的性能损耗;
  • 开发者友好,让开发者专注于业务逻辑,无需手动管理内存。

1.2 编译器插桩机制

ARC 的实现依赖于编译器插桩:在源码编译阶段,编译器会自动在合适的位置插入 retain、release、autorelease 等内存管理指令。开发者无需手动调用这些方法,编译器会根据变量作用域、闭包捕获等场景自动生成相应的代码。

例如,以下 Swift 代码:

func foo() {let obj = MyClass()obj.doSomething()
}

Swift 编译器会在需要时插入 swift_retain 和 swift_release 调用,编译后,等价于如下伪代码:

let obj = swift_alloc(MyClass)
swift_retain(obj)
obj.doSomething()
swift_release(obj)

开发者无需手动管理这些操作,编译器会根据变量作用域、闭包捕获等场景自动插入合适的指令。

1.3 retain/release 的底层原理

每当你增加或减少一个对象的强引用时,Swift 底层会自动用 swift_retain 或 swift_release 这类函数。

  • retain:将对象的引用计数加一。
  • release:将对象的引用计数减一。如果计数减到零,系统会自动调用对象的析构方法(deinit),并释放其占用的内存。

在多线程环境下,可能会有多个线程同时对同一个对象进行 retain 或 release 操作。为了避免数据竞争和计数错误,Swift 在底层实现中采用了原子操作(atomic operation),例如 C++11 的 std::atomic。这样可以确保每一次引用计数的增加或减少都是安全且不可分割的,避免出现“加错”或“减错”的情况,从而保证了 ARC 在多线程下的正确性和稳定性。

1.4 对象销毁的完整流程

  1. 当引用计数减为零:当最后一个强引用消失,release 操作使引用计数变为 0。
  2. 调用析构方法:Swift 自动调用对象的 deinit 方法(Objective-C 为 dealloc),用于资源清理、通知等。
  3. 释放成员变量:对象的所有成员变量(包括强引用的其他对象)会被依次 release,递归触发它们的引用计数变化。
  4. 回收内存:对象的内存块被系统回收,彻底释放。

1.5 ARC 的作用范围

  • ARC 主要作用于类(class)类型的实例。只有引用类型(如 class、NSObject 及其子类)才有引用计数,受 ARC 管理。
  • 结构体(struct)和枚举(enum)为值类型,生命周期由作用域自动管理,不参与 ARC。

1.6 引用计数的类型

ARC 支持多种引用类型,不同类型对引用计数的影响不同:

  • 强引用(strong):默认引用类型,持有对象时引用计数加一,保证对象在引用期间不会被释放。
  • 弱引用(weak):不增加引用计数,目标对象释放后自动置为 nil,常用于避免循环引用。
  • 无主引用(unowned):同样不增加引用计数,但目标对象释放后不会自动置为 nil,如果访问已释放对象会导致程序崩溃。适用于生命周期绑定但不会为 nil 的场景。

二、Swift 对象的内存布局与引用计数存储

在理解 ARC 的底层实现时,首先要搞清楚 Swift 类对象在内存中的真实样子。其实,每个 Swift 类对象在内存中都包含了类型信息、引用计数和实际的数据。下面我们用通俗的方式来拆解。

2.1 Swift 对象的内存结构是什么样的?

你可以把 Swift 的类对象想象成一排盒子,每个盒子里装着不同的信息。

假设你有这样一个类:

class Dog {var age: Int32      // 4字节var weight: Double  // 8字节
}

当你写 let dog = Dog() 时,系统会在内存里为这个对象分配一块连续的空间。

这块空间的内容和顺序大致如下:

| 盒子1 | 盒子2 | 盒子3 | 盒子4 | 盒子5 |

|---------------|-----------------|---------|---------|---------|

| isa指针 | 引用计数/标志位 | padding | age属性 | weight属性 |

每个盒子装的是什么?
  • isa指针:告诉系统“我是什么类型”,比如“我是Dog类”。用于类型识别、方法分发等。
  • 引用计数/标志位:记录有多少人在用这个对象(ARC用来决定何时释放内存),有时还包含一些标志位(如是否用旁表、是否已释放等)。
  • padding:有时候为了让后面的数据对齐,系统会加点“空盒子”。
  • age属性:你定义的 age 变量。
  • weight属性:你定义的 weight 变量。

2.2 伪代码结构

struct DogObject {uintptr_t isa;         // 8字节,类型信息uint32_t refCount;     // 4字节,引用计数uint32_t padding;      // 4字节,填充int32_t age;           // 4字节,age属性double weight;         // 8字节,weight属性
};
2.2.1 为什么要有 padding(填充)?

因为有些数据类型(比如 Double)要求在内存中“对齐”,这样 CPU 读取更快。

如果前面不是8的倍数,就会加点“空盒子”让后面的数据排整齐。

2.2.2 假设内存地址从低到高排列:

| isa | refCount | padding | age | weight |

  • isa(8字节)
  • refCount(4字节)
  • padding(4字节,为了让 weight 对齐)
  • age(4字节)
  • weight(8字节)

2.3 引用计数的内容和格式

引用计数字段不仅仅是一个简单的数字,通常还包含一些标志位,比如:

  • 是否已经被释放
  • 是否正在使用旁表
  • 是否是无主引用(unowned)

这些信息一般通过位运算存储在同一个字段里。

2.4 引用计数的存储方式

Swift 的引用计数有两种存储方式:

2.4.1. 内联计数(Inline Refcount)

大多数情况下,Swift 对象的引用计数直接存储在对象头部(即结构体中的 refCount 字段)。这种方式被称为内联计数(Inline Refcount)。

2.4.1.1 为什么要这样设计?
  • 高效访问:引用计数和对象本身在同一块内存区域,CPU 读取和修改都非常快,无需额外寻址。
  • 空间节省:绝大多数对象的引用计数都不会很大,直接用对象头部的几个字节就能满足需求,避免了为每个对象单独分配计数空间。
  • 局部性原理:对象和其引用计数在内存上相邻,提升了缓存命中率,进一步加快了访问速度。
2.4.2. 旁表(Side Table)

在 Swift 的 ARC 内存管理体系中,Side Table(旁表)是一种用于辅助管理对象引用计数和其他元数据的全局数据结构。它的本质是一个哈希表。key 是对象的内存地址,value 是该对象的引用计数及相关信息

2.4.2.1 为什么需要 Side Table?

大多数情况下,对象的引用计数直接存储在对象头部(内联存储),这样效率最高。但有些特殊场景下,内联存储就不够用了:

    • 引用计数溢出:比如一个对象被成千上万个地方强引用,内联计数位数不够用。
    • 需要存储额外信息:如弱引用(weak)、无主引用(unowned)等元数据,或者调试信息。
    • 对象参与复杂的内存管理策略:如与 Objective-C 混用时的特殊处理。

    这时,Swift 会自动将该对象的引用计数和相关信息迁移到 Side Table 中。

    2.4.2.2 Side Table 的结构和原理

    Side Table 可以理解为一个全局的哈希表,结构大致如下(伪代码):

    struct SideTableEntry {int strongRefCount;   // 强引用计数int unownedRefCount;  // 无主引用计数// 可能还有其他元数据
    }std::unordered_map<void*, SideTableEntry> sideTable;
    • 查找:通过对象的内存地址查找对应的 Side Table Entry。
    • 操作:对 Entry 里的计数进行原子加减,保证线程安全。
    2.4.2.3 Side Table 的性能影响
    • 绝大多数对象不会用到 Side Table,只有极少数“特殊对象”才会迁移到旁表。
    • 这样设计的好处是:常规对象的引用计数操作非常快,只有极端情况才会牺牲一点性能,换取更大的灵活性和安全性。
    2.4.2.4 Side Table 与弱引用(weak)的关系
    • 当你在 Swift 里声明 weak 属性时,系统会为该对象在 Side Table 里登记一份弱引用信息。
    • 当对象引用计数为 0、即将销毁时,Side Table 会负责把所有指向它的 weak 指针自动置为 nil,防止野指针。
    2.4.2.5 Side Table 的生命周期
    • Side Table 的 Entry 会在对象销毁后自动清理,避免内存泄漏。
    • 你无需手动管理 Side Table,Swift 运行时会自动处理。

    Side Table 是 Swift ARC 内存管理体系中一个“幕后英雄”,它为极端场景下的对象引用计数和弱引用管理提供了强有力的支持。虽然大多数开发者感受不到它的存在,但正是有了 Side Table,Swift 才能兼顾高性能与高灵活性,安全地管理各种复杂对象的生命周期。

    三、Swift 与 Objective-C ARC 的底层差异

    在 iOS 开发中,Swift 和 Objective-C 都采用了 ARC(自动引用计数)来管理内存,但它们在底层实现上有一些重要的区别。理解这些差异,有助于我们在混合开发或排查内存问题时更加得心应手。

    3.1 引用计数的存储方式

    • Objective-C 的对象引用计数不会存储在对象头部。每个 OC 对象的头部只有一个 isa 指针(指向类的元数据)。引用计数信息存储在一个全局的 Side Table(旁表)中。每次 retain/release 操作,系统会通过对象地址查找 Side Table 并更新计数。这种方式实现简单,但频繁查表会带来一定性能开销。
    • Swift 对象的引用计数更为高效。大多数情况下,Swift 会把引用计数直接存储在对象头部的某些比特位中(Inline Refcount)。只有在引用计数非常大或需要特殊管理时,才会像 Objective-C 一样转移到旁表。这种设计减少了查表次数,提高了性能。

    3.2 对象元数据结构

    • 在 Objective-C 中,每个对象的内存布局非常简单。对象的头部第一个字段就是一个 isa 指针。这个指针指向该对象所属类的元数据(class object),元数据中包含了方法列表、属性列表等信息。通过 isa 指针,Objective-C 运行时可以实现方法查找、类型判断等功能。
    • Swift 的类对象同样在头部包含一个指向元数据的指针,这个指针在 Swift 中通常被称为metadata pointer,有时也叫 isa。这个指针同样位于对象内存的起始位置,即对象的第一个字段。该指针指向 Swift 的类型元数据(metadata),元数据结构比 Objective-C 更复杂,包含类型信息、协议、方法表等。这样可以支持更多高级特性,比如泛型和协议扩展。

    3.3 引用类型的差异

    • Objective-C 只有强引用(strong)和弱引用(weak),没有无主引用(unowned)的概念。弱引用在对象释放后会自动置为 nil,防止野指针。
    • Swift 除了 strong 和 weak,还引入了 unowned(无主引用)。unowned 引用不会增加引用计数,但对象释放后不会自动置为 nil。如果访问已释放的对象会导致崩溃。unowned 适用于生命周期绑定但不会为 nil 的场景,比如 delegate。

    3.4 ARC 的桥接与兼容

    Swift 和 Objective-C 的对象可以互相引用,ARC 机制能够自动适配。例如,Swift 的类继承自 NSObject 时,ARC 会自动桥接引用计数,保证内存安全。开发者在混合开发时无需手动干预,大多数情况下可以无缝协作。

    3.5 小结

    Swift 和 Objective-C 的 ARC 虽然目标一致,但底层实现各有优化。Swift 更注重性能和类型安全,采用了更高效的引用计数存储方式,并引入了 unowned 引用类型。了解这些差异,有助于我们写出更高效、更安全的代码,尤其是在 Swift 与 Objective-C 混合开发时。

    四、内存管理中的底层陷阱与调试技巧

    4.1 循环引用的本质与解决方法

    在 ARC 机制下,循环引用(Retain Cycle)是最常见的内存泄漏问题。它的本质是:两个或多个对象之间互相持有强引用,导致它们的引用计数永远不会变为 0,内存无法被释放。

    举个例子:
    class Person {var pet: Pet?
    }class Pet {var owner: Person?
    }

    如果 Person 和 Pet 互相强引用对方,即使它们都不再被外部引用,也不会被释放,造成内存泄漏。

    解决方法:

    Swift 提供了两种弱引用方式:

    • weak(弱引用):不会增加引用计数,引用对象被释放后自动变为 nil,适合可选类型。
    • unowned(无主引用):不会增加引用计数,引用对象被释放后不会变为 nil,适合生命周期一致的非可选类型。

    推荐做法:

    在需要打破循环引用的地方,将一方声明为 weak 或 unowned,比如:

    class Pet {weak var owner: Person?
    }

    这样就能保证对象在不再被需要时正确释放。

    4.2 闭包与 self 的循环引用

    Swift 的闭包(Closure)默认会强引用捕获的对象,尤其是 self。如果在类中将闭包作为属性,并在闭包内访问 self,就会形成循环引用。

    典型场景:
    class MyClass {var closure: (() -> Void)?func setup() {closure = {self.doSomething()}}
    }
    解决方法:

    使用捕获列表,将 self 以 weak 或 unowned 方式捕获:

    closure = { [weak self] inself?.doSomething()
    }

    这样可以有效避免循环引用。

    如果对闭包有疑问,可以看我的博客:Swift闭包(Closure)深入解析与底层原理

    4.3 AutoreleasePool 的底层机制

    虽然 Swift 很少直接用 @autoreleasepool,但在与 Objective-C 代码交互或大量临时对象创建时,AutoreleasePool 依然很重要。

    AutoreleasePool 的本质是一个栈结构,存储了“待释放”的对象指针。每当 pool 被销毁或“排空”时,栈中的对象会统一调用 release,从而释放内存。

    典型场景:

    在 for 循环中大量创建临时对象时,可以手动包裹 @autoreleasepool,及时释放内存,避免内存峰值过高。

    for _ in 0..<10000 {autoreleasepool {// 创建大量临时对象}
    }

      5.4 内存泄漏与僵尸对象的调试

      Swift 和 iOS 提供了多种工具帮助我们发现和定位内存问题:

        • Xcode Instruments:使用 Leaks、Allocations 工具可以追踪对象的分配、引用计数变化和泄漏点。
        • 静态分析:Xcode 的 Analyze 功能可以在编译时发现潜在的内存泄漏。
        • NSZombieEnabled:设置环境变量 NSZombieEnabled=YES,可以让已释放的对象变成“僵尸对象”,帮助定位野指针访问问题。

        总结

        本文系统梳理了 Swift 与 iOS 的内存管理机制,从 ARC 的底层原理、对象内存布局、引用计数存储方式,到 Swift 与 Objective-C ARC 的差异,再到常见内存陷阱与调试技巧,力求让开发者对 iOS 内存管理有更深入、全面的理解。

        Swift 的 ARC 通过编译器插桩自动管理对象生命周期,极大简化了开发者的工作,但其底层实现却蕴含诸多细节与优化。例如,Swift 采用内联引用计数与旁表(Side Table)相结合的方式,既保证了性能,又兼顾了灵活性和安全性。与 Objective-C 相比,Swift 在类型安全、引用类型(如 unowned)等方面也做了更多优化。

        在实际开发中,循环引用、闭包捕获 self、AutoreleasePool 的使用等,都是内存管理的高频考点。只有理解底层原理,才能在遇到复杂场景时游刃有余,写出高效、健壮的代码。善用 Xcode Instruments、静态分析、NSZombieEnabled 等工具,可以帮助我们及时发现和定位内存问题,提升代码质量。

        总之,内存管理是每一位 iOS 开发者的必修课。希望本文能帮助你建立起系统的知识体系,少踩坑,多写优雅高效的 Swift 代码。如果你有更多关于 Swift 内存管理的疑问或经验,欢迎在评论区交流讨论!


        如果觉得本文对你有帮助,欢迎点赞、收藏、关注我,后续会持续分享更多 iOS 底层原理与实战经验!

          相关文章:

          Swift与iOS内存管理机制深度剖析

          前言 内存管理是每一位 iOS 开发者都绕不开的话题。虽然 Swift 的 ARC&#xff08;自动引用计数&#xff09;极大简化了开发者的工作&#xff0c;但只有深入理解其底层实现&#xff0c;才能写出高效、健壮的代码&#xff0c;避免各种隐蔽的内存问题。本文将从底层原理出发&…...

          怎样给MP3音频重命名?是时候管理下电脑中的音频文件名了

          在处理大量音频文件时&#xff0c;给这些文件起一个有意义的名字可以帮助我们更高效地管理和查找所需的内容。通过使用专业的文件重命名工具如简鹿文件批量重命名工具&#xff0c;可以极大地简化这一过程。本文将详细介绍如何利用该工具对 MP3 音频文件进行重命名。 步骤一&am…...

          当AI浏览器和AI搜索替代掉传统搜索份额时,老牌的搜索引擎市场何去何从。

          AI搜索与传统搜索优劣势分析 AI搜索优势 理解和处理查询方式更智能&#xff1a;利用自然语言处理&#xff08;NLP&#xff09;和机器学习技术&#xff0c;能够更好地理解用户的意图和上下文&#xff0c;处理复杂的问答、长尾问题以及多轮对话&#xff0c;提供更为精准和相关的…...

          快速上手非关系型数据库-MongoDB

          简介 MongoDB 是一个基于文档的 NoSQL 数据库&#xff0c;由 MongoDB Inc. 开发。 NoSQL&#xff0c;指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写&#xff0c;是对不同于传统的关系型数据库的数据库管理系统的统称。 MongoDB 的设计理念是为了应对大数据量、…...

          【C++学习笔记】深入理解虚函数和多态

          文章目录 1. 基本概念1.1 虚函数1.2 虚函数表1.3 虚函数表指针1.4 虚函数表在支持多态方面的工作原理 2. 类对象在内存中的布局参考 1. 基本概念 1.1 虚函数 类的成员函数&#xff0c;并不占用类对象的内存空间。 类中有虚函数&#xff0c;编译器会向类中插入一个看不见的成…...

          STM32F103C8T6信息

          STM32F103C8T6 完整参数列表 一、核心参数 内核架构‌ ARM Cortex-M3 32位RISC处理器 最大主频&#xff1a;72 MHz&#xff08;基于APB总线时钟&#xff09; 运算性能&#xff1a;1.25 DMIPS/MHz&#xff08;Dhrystone 2.1基准&#xff09; 总线与存储‌ 总线宽度&#xff…...

          用手机相册教我数组概念——照片分类术[特殊字符][特殊字符]

          目录 前言一、现实场景1.1 手机相册的照片管理1.2 照片分类的需求 二、技术映射2.1 数组与照片分类的对应关系2.2 数组索引与照片标签的类比 三、知识点呈现3.1 数组的基本概念3.2 数组在编程中的重要性3.3 数组的定义与初始化3.4 数组的常见操作&#xff08;增删改查&#xff…...

          Node.js CSRF 保护指南:示例及启用方法

          解释 CSRF 跨站请求伪造 (CSRF/XSRF) 是一种利用用户权限劫持会话的攻击。这种攻击策略允许攻击者通过诱骗用户以攻击者的名义提交恶意请求,从而绕过我们的安全措施。 CSRF 攻击之所以可能发生,是因为两个原因。首先,CSRF 攻击利用了用户无法辨别看似合法的 HTML 元素是否…...

          【Linux】VSCode用法

          描述 部分图片和经验来源于网络&#xff0c;若有侵权麻烦联系我删除&#xff0c;主要是做笔记的时候忘记写来源了&#xff0c;做完笔记很久才写博客。 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 安装环境及运行C/C 1.1 安装及配置步骤 1.2 运…...

          来聊聊JVM中安全点的概念

          文章目录 写在文章开头详解safepoint基本概念什么是安全点?为什么需要安全点JVM如何让线程跑到最近的安全点线程什么时候需要进入安全点JVM如何保证线程高效进入安全点如何设置安全点用一次GC解释基于安全点的STW实践-基于主线程休眠了解安全点的工作过程代码示例基于日志印证…...

          【AI面试准备】负责所有Al产品的模型能力评估及测试,保障AI产品的质量

          面试岗位提出这个要求:负责所有Al产品的模型能力评估及测试,保障AI产品的质量。 目录 **一、AI产品模型评估的核心框架**1. **评估维度全景图**2. **质量保障全流程****二、关键模型类型评估策略**1. **分类模型(如推荐系统)**2. **生成模型(如GPT、Stable Diffusion)**…...

          Nginx — http、server、location模块下配置相同策略优先级问题

          一、配置优先级简述 在 Nginx 中&#xff0c;http、server、location 模块下配置相同策略时是存在优先级的&#xff0c;一般遵循 “范围越小&#xff0c;优先级越高” 的原则&#xff0c;下面为你详细介绍&#xff1a; 1. 配置继承关系 http 块&#xff1a;作为全局配置块&…...

          mysql数据库备份与恢复方法

          一、备份方法 逻辑备份&#xff08;基于SQL语句&#xff09; 使用mysqldump工具 全库备份&#xff1a;mysqldump -u root -p --all-databases > all_databases_backup.sql单库备份&#xff1a;mysqldump -u root -p jztdb > full_backup.sql排除特定表&#xff1a;--igno…...

          实验三 软件黑盒测试

          实验三 软件黑盒测试使用测试界的一个古老例子---三角形问题来进行等价类划分。输入三个整数a、b和c分别作为三角形的三条边&#xff0c;通过程序判断由这三条边构成的三角形类型是等边三角形、等腰三角形、一般三角形或非三角形(不能构成一个三角形)。其中要求输入变量&#x…...

          线性代数—向量与矩阵的范数(Norm)

          参考链接&#xff1a; 范数&#xff08;Norm&#xff09;——定义、原理、分类、作用与应用 - 知乎 带你秒懂向量与矩阵的范数(Norm)_矩阵norm-CSDN博客 什么是范数&#xff08;norm&#xff09;&#xff1f;以及L1,L2范数的简单介绍_l1 norm-CSDN博客 范数&#xff08;Norm…...

          Umi-OCR项目(1)

          最近接触到了一个项目&#xff0c;我在想能不能做出点东西出来。 目标&#xff1a;识别一张带表格的图片&#xff0c;要求非表格内容和表格内容都要识别得很好&#xff0c;并且可视化输出为word文档。 下面是第一步的测试代码&#xff0c;测试是否能够调用ocr能力。 import re…...

          【业务领域】电脑主板芯片电路结构

          前言 由前几期视频合集(零基础自学计算机故障排除—7天了解计算机开机过程)&#xff0c;讲解了POST的主板软启动过程&#xff1b;有不少网友留言、私信来问各种不开机的故障&#xff0c;但大多网友没能能过我们的这合集视频&#xff0c;很好的理清思路&#xff0c;那这样的情况…...

          pandas读取Excel数据(.xlsx和.xls)到treeview

          对于.xls文件&#xff0c;xlrd可能更合适&#xff0c;但需要注意新版本的xlrd可能不支持xlsx&#xff0c;不过用户可能同时需要处理两种格式&#xff0c;所以可能需要结合openpyxl和xlrd&#xff1f;或者直接用pandas&#xff0c;因为它内部会处理这些依赖。 然后&#xff0c;…...

          【Nginx】负载均衡配置详解

          Nginx作为高性能的HTTP服务器和反向代理服务器&#xff0c;提供了强大的负载均衡功能。本文将详细介绍Nginx负载均衡的配置方法和相关策略。 一、基础负载均衡配置 1.单服务示例配置 配置nginx.conf模块 在Nginx配置文件中定义upstream模块&#xff1a; worker_processes a…...

          JVM——垃圾收集策略

          GC的基本问题 什么是GC&#xff1f; GC 是 garbage collection 的缩写&#xff0c;意思是垃圾回收——把内存&#xff08;特别是堆内存&#xff09;中不再使用的空间释放掉&#xff1b;清理不再使用的对象。 为什么要GC&#xff1f; 堆内存是各个线程共享的空间&#xff0c…...

          马克·雷伯特:用算法让机器人飞奔的人

          名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 马克雷伯特:用算法让机器人飞奔的人 一、天才的起点 在机器人领域,有一个名字如雷贯耳——马克雷伯特(Marc Raibert)。作为波士顿动力公司(Boston…...

          信创系统资产清单采集脚本:主机名+IP+MAC 一键生成 CSV

          原文链接&#xff1a;信创系统资产清单采集脚本&#xff1a;主机名IPMAC 一键生成 CSV Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在信创终端操作系统上自动批量采集主机名、IP 和 MAC 并导出为 CSV 表格的实战文章&#xff01;本方案使用 sshpass 和 Bash 脚本…...

          SpringBoot获取用户信息常见问题(密码屏蔽、驼峰命名和下划线命名的自动转换)

          文章目录 一、不返回password字段二、返回的createTime和updateTime为空原因解决&#xff1a;开启驼峰命名和下划线命名的自动转换 设置返回的日期格式 一、不返回password字段 在字段上面添加JsonIgnore注解即可 JsonIgnore // 在把对象序列化成json字符串时&#xff0c;忽略…...

          小刚说C语言刷题—1602总分和平均分

          1.题目描述 期末考试成绩出来了&#xff0c;小明同学语文、数学、英语分别考了 x、y、z 分&#xff0c;请编程帮助小明计算一下&#xff0c;他的总分和平均分分别考了多少分&#xff1f; 输入 三个整数 x、y、z 分别代表小明三科考试的成绩。 输出 第 11行有一个整数&…...

          C++编译之(5)-cmake/CMakeLists.txt的编译使用教程

          C++编译之(5)-cmake/CMakeLists.txt的编译使用教程 上一节,点这里 1、如何查看cmake的配置参数 那么如何查看当前配置的参数呢,我们可以使用-L参数 cmake .. -L # cmake .. -LAH完全使用命令行,则可以通过多次重复使用cmake … -DOPTION1=ON -D OPTION2=ON配置制定选项;并…...

          Mac下安装Python3,并配置环境变量设置为默认

          下载Python 访问Python官方网站 https://www.python.org/ 首先获得python3安装路径 执行命令&#xff1a; which python3 以我这台电脑为例&#xff0c;路径为&#xff1a;/Library/Frameworks/Python.framework/Versions/3.9/bin/python3 编辑 bash_profile 文件 然后用 vim 打…...

          Linux-04-用户管理命令

          一、useradd添加新用户: 基本语法: useradd 用户名:添加新用户 useradd -g 组名 用户:添加新用户到某个组二、passwd设置用户密码: 基本语法: passwd 用户名:设置用户名密码 三、id查看用户是否存在: 基本语法: id 用户名 四、su切换用户: 基本语法: su 用户名称:切换用…...

          【进阶】--函数栈帧的创建和销毁详解

          目录 一.函数栈帧的概念 二.理解函数栈帧能让我们解决什么问题 三.相关寄存器和汇编指令知识点补充 四.函数栈帧的创建和销毁 4.1.调用堆栈 4.2.函数栈帧的创建 4.3 函数栈帧的销毁 一.函数栈帧的概念 --在C语言中&#xff0c;函数栈帧是指在函数调用过程中&#xff0c;…...

          Hadoop伪分布式模式搭建全攻略:从环境配置到实战测试

          引言 作为大数据生态的基石,Hadoop凭借其高可靠性、扩展性成为分布式计算的首选框架。本文将手把手带你完成Hadoop伪分布式模式部署,通过单节点模拟集群环境,为后续学习MapReduce、YARN等核心组件打下基础 目录 引言 Hadoop 发展历史 1.1 起源(2002–2005) 1.1 安装JDK…...

          Transformer:颠覆深度学习的架构革命与技术演进

          2017年&#xff0c;谷歌团队在论文《Attention Is All You Need》中提出的Transformer架构&#xff0c;彻底改变了人工智能对序列数据的处理范式。它不仅解决了传统循环神经网络&#xff08;RNN&#xff09;的长期依赖和并行化难题&#xff0c;更催生了BERT、GPT等划时代模型&a…...