【iOS】OC源码阅读——alloc源码分析
文章目录
- 前言
- 基本调试方法
- alloc
- alloc函数逐步调试
- 空类检查
- 快速路径:默认内存分配
- 慢速路径:自定义内存分配
- slowpath和fastpath
- alloc核心操作
- cls->instanceSize:计算所需内存大小
- 内存字节对齐原则
- 为什么要16字节对齐
- 内存字节对齐总结
- 其他
- 总结
前言
之前笔者简单学习了Objective-c,这段时间在阅读OC源码,通过阅读obj838来深入理解代码的运行机制、设计思想及实现细节。本篇博客主要分享一下我通过阅读和调试alloc部分的源码所学到的东西和遇到的问题。(笔者这里调试的源码为906,点击下载)
首先,阅读源码时我们发现,虽然我们编程使用的是OC语言,但是底层源码大部分使用的是C语言或者C++。
基本调试方法
首先打开我们随机一个项目,在左侧找到断点图标。
找到断点图标后,点击下方添加按钮选择“Symbolic Breakpoint”进行断点添加。
在“Symbol”里输入想要添加断点的地方,然后点击下面的“Add Action”。
在对alloc方法进行断点测试的时候,一个项目中可能涉及多个alloc,我们可以在具体需要测试的位置上进行添加断点,运行程序时在走到这部分断点的时候,再打开上面新增的alloc符号断点,因为alloc的调用有很多,如果开启了就不能准确的定位到我们设定的断点处。
断点打开状态:
断点关闭状态:
然后看情况选择点击Continue、Step Over或Step In进行逐步调试。
xcode调试按钮从左到右依次是:
断点符:可以用来整体关闭或打开断点。
继续运行(Continue):恢复程序执行,直到遇到下一个断点或程序结束。
步过 (Step Over):逐行执行代码,不进入函数/方法内部。
步进进入 (Step In):进入当前行调用的函数/方法内部(逐行调试)。
步出 (Step Out):执行完当前函数剩余代码,直接跳出到调用位置。
alloc
在OC语言中,alloc方法是创建对象实例的核心入口,其底层实现涉及内存分配、类结构管理和运行时机制。
上述代码依次输出GGObject对象的内容、内存地址、指针地址。
首先,我们通过运行这部分代码可以发现obj1、obj2、obj3指向的是同一个内存空间,因为其内容、内存地址是相同的,但是他们的指针地址是不同的。下面我们来探索alloc在这中间到底做了什么。
alloc函数逐步调试
我们添加断点,运行代码,打开alloc断点,然后根据不同情况进行逐步调试。
第一步,点击Step In进入alloc的源码,我们可以看到:
第二步,继续Step In就可以进入_objc_rootAlloc的源码实现:
第三步,接着Step In进入callAlloc的源码:
这里是用于对象内存分配的核心函数,其作用是根据类的内存分配策略(默认或自定义)选择合适的分配方法。
首先,函数签名是:
static ALWAYS_INLINE id //ALWAYS_INLINE:强制内联展开,避免函数调用开销(性能敏感场景)
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
//参数一:目标类(Class 类型) 参数二:是否检查类是否为 nil 参数三:是否调用 allocWithZone: 方法(默认调用 alloc)
空类检查
if (slowpath(checkNil && !cls)) return nil;//slowpath:宏定义,表示“慢速路径”(通常用于条件分支预测失败的场景)
主要是为了防止向空类发送消息,避免程序崩溃。(如果 checkNil 为 true 且类指针 cls 为 nil,直接返回 nil)
快速路径:默认内存分配
if (fastpath(!cls->ISA()->hasCustomAWZ())) {return _objc_rootAllocWithZone(cls, nil);
}
//fastpath:宏定义,表示“快速路径”(条件分支预测成功的场景)
//cls->ISA()->hasCustomAWZ():检查类或其元类是否实现了自定义的 alloc/allocWithZone: 方法
//(hasCustomAWZ:全称 hasCustomAllocationWithZone;若返回 false,表示使用默认内存分配逻辑)
//_objc_rootAllocWithZone:默认内存分配函数,直接调用 malloc 或内存池分配内存,不调用 alloc 方法
慢速路径:自定义内存分配
if (allocWithZone) {return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
} else {return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}
//objc_msgSend:Objective-C 运行时核心函数,用于向对象发送消息(调用方法)
//类型转换:将objc_msgSend强制转换为特定签名的函数指针,确保参数和返回值正确
//参数:allocWithZone::传递 nil 作为 _NSZone 参数
如果类实现了自定义的 alloc/allocWithZone: 方法,则通过消息发送机制调用。若 allocWithZone 为 true,调用 allocWithZone:;
否则,调用 alloc。
slowpath和fastpath
首先,这里的slowpath和fastpath是Objective-C运行时中用于分支预测优化的宏。这里的fastpath用于提示编译器某个条件大概率成立,而slowpath则相反,提示条件大概率不成立。
  这些宏通常使用__builtin_expect来实现,帮助编译器优化代码布局,提高执行效率。这里我们通过在代码中搜索#define fastpath可以找到这个宏定义的位置文件。
在C/C++中,__builtin_expect是GCC的一个内置函数,用于给编译器提示条件分支的预期走向,这样编译器可以进行优化,比如调整指令顺序,让经常执行的分支更靠近处理器的前端,减少分支预测失败的开销。
这里,通过 __builtin_expect 提示编译器条件分支的预期走向,优化指令布局,减少分支预测失败的开销,分离高频路径(fastpath)和低频路径(slowpath),提升代码执行效率。
fastpath的参数x被期望为真(即1),而slowpath的参数x被期望为假(0),将 x 为真的分支代码紧凑排列,减少跳转;将 x 为假的分支代码放在较远位置,减少对主流程的影响。
了解完上述代码中涉及的内容后,我们进行Step Over,此时来到fastpath。
关于这里的!cls->ISA()->hasCustomAWZ():
cls——目标类对象(Class 类型)。
cls->ISA()——获取类的元类(Meta Class)。
hasCustomAWZ()——检查类或其元类是否实现了自定义的 alloc 或 allocWithZone: 方法。
!——逻辑取反,表示“没有自定义分配方法”。
这里主要用于判断是否使用默认内存分配路径(快速路径)或自定义分配路径(慢速路径)。
条件为真时(!hasCustomAWZ()):类或其元类未实现自定义的 alloc/allocWithZone:,使用默认分配逻辑(_objc_rootAllocWithZone),即进入这里:
条件为假时:存在自定义分配方法,需通过消息发送(objc_msgSend)调用,即进入这里:
在这个过程中:
cls->ISA() 返回类的元类指针(例如:NSObject 的元类是 NSObject 自身(根元类))。
元类(Meta Class):
在 Objective-C 中,每个类都有一个元类,用于存储类方法(如 alloc、allocWithZone:)。
实例方法的查找路径:实例 -> 类 -> 父类。
类方法的查找路径:类 -> 元类 -> 根元类。
我们Step Over到fastpath的返回语句里,Step In就可以看到_objc_rootAllocWithZone的实现源码:
_objc_rootAllocWithZone 是 Objective-C 运行时中用于创建对象实例的底层函数,主要负责分配内存并初始化对象头信息(如 isa 指针)。它是 alloc 和 allocWithZone: 方法的最终实现,直接与内存分配器交互。
参数一(cls)——目标类。
参数二(flags(第二个参数 0))——控制分配行为的标志位。常见值:
OBJECT_CONSTRUCT_CALL_BADALLOC:在内存分配失败时抛出异常。
其他标志可能控制是否跳过初始化(如 FAST_ALLOC)。
参数三(OBJECT_CONSTRUCT_CALL_BADALLOC)——宏定义,表示分配失败时调用 objc_abort 或抛出异常。
随后,我们继续进入到_class_createInstance源码(这里是alloc实现的核心源码),为了方便做注释,笔者将这部分代码copy了过来:
static ALWAYS_INLINE id
_class_createInstance(Class cls, //目标类,必须已加载(isRealized())size_t extraBytes,//额外内存(通常为0),用于子类扩展int construct_flags = OBJECT_CONSTRUCT_NONE,//构造标志bool cxxConstruct = true,//是否调用C++构造函数size_t *outAllocatedSize = nil)//返回实际分配的内存大小
{ASSERT(cls->isRealized());//(isRealized())确保类已加载到运行时;未实现时,触发断言,防止未初始化类被使用// Read class's info bits all at once for performancebool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();//类是否有C++构造函数bool hasCxxDtor = cls->hasCxxDtor();//类是否有C++析构函数bool fast = cls->canAllocNonpointer();//是否使用非指针isa(优化引用计数存储)size_t size;size = cls->instanceSize(extraBytes);//返回类实例的总内存大小(包括 isa、引用计数、成员变量)if (outAllocatedSize) *outAllocatedSize = size;id obj = objc::malloc_instance(size, cls);//底层内存分配函数,可能调用 malloc 或内存池。if (slowpath(!obj)) {if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {return _objc_callBadAllocHandler(cls);}return nil;}//初始化isa指针if (fast) {obj->initInstanceIsa(cls, hasCxxDtor);//使用非指针isa} else {// Use raw pointer isa on the assumption that they might be// doing something weird with the zone or RR.obj->initIsa(cls);//使用原始指针isa}if (fastpath(!hasCxxCtor)) {return obj;//无C++构造函数}//有C++构造函数construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;return object_cxxConstructFromClass(obj, cls, construct_flags);
}
在obj838中,这部分源码如下:
_class_createInstance 函数是对象实例化的核心,主要完成以下任务:
内存分配:调用 malloc 或类似函数分配内存。
对象头初始化:设置 isa 指针(指向类的元类)。
引用计数初始化:初始化 retainCount 等字段。
构造函数调用:若类实现了 +alloc 或 +allocWithZone: 的自定义逻辑,可能在这里调用。
由此,我们可以大致了解_class_createInstance函数的实现流程(与_class_createInstanceFromZone同理):
alloc核心操作
核心操作都位于calloc方法中
cls->instanceSize:计算所需内存大小
计算需要开辟内存的大小的执行流程如下所示:
-
进入instanceSize的源码实现
-
进入fastInstanceSize(快速计算内存大小)的源码实现
-
跳转至align16(16字节对齐算法)的源码实现
内存字节对齐原则
- 对齐值
数据类型的对齐值是其大小和硬件架构共同决定的。
常见对齐值:
- 起始地址必须是整数倍
数据的内存起始地址必须是对齐值的整数倍。
示例:
一个 int(4字节)的起始地址应为 0x1000, 0x1004, 0x1008 等。
一个 double(8字节)的起始地址应为 0x2000, 0x2008 等。
- 结构体/类的对齐
结构体或类的对齐值由其成员的最大对齐值决定。
示例:
struct Example {char c; // 1字节(对齐值1)int i; // 4字节(对齐值4)
};
字符 c 后需插入 3 字节填充,使 i 从 4 字节地址开始。
结构体总大小为 1 + 3 (填充) + 4 = 8 字节,对齐值为 4 字节。
为什么要16字节对齐
- 对齐访问允许 CPU 通过单次内存操作读取或写入数据:
通常内存是由一个个字节组成的,cpu在存取数据时,并不是以字节为单位存储,而是以块为单位存取,块的大小为内存存取力度。频繁存取字节未对齐的数据,会极大降低cpu的性能,所以可以通过减少存取次数来降低cpu的开销。
eg:例如:64 位 CPU 一次可读取 8 字节数据。若数据对齐到 8 字节边界,只需一次访问;若未对齐,可能需要两次访问。
- 16字节对齐有利于性能优化,提高内存访问效率:
16字节对齐,是由于在一个对象中,第一个属性isa占8字节,当然一个对象肯定还有其他属性,当无属性时,会预留8字节,即16字节对齐,如果不预留,相当于这个对象的isa和其他对象的isa紧挨着,容易造成访问混乱。
内存字节对齐总结
在字节对齐算法中,对齐的主要是对象,而对象的本质则是一个 struct objc_object的结构体。
结构体在内存中是连续存放的,所以可以利用这点对结构体进行强转。
苹果早期是8字节对齐,现在是16字节对齐。
算法原理
目标:将原始内存大小 x 向上取整到最近的 16字节对齐 的边界。
公式:对齐后的大小=(x+15) & ( 15)
步骤:
- 加15:将原始大小 x 加上 15,确保结果覆盖所有可能的余数。
- 取反15:~15 的二进制为 1111 1111 1111 0000(以32位为例),其作用是保留高位,清零低4位。
- 按位与操作:通过 (x + 15) & (~15),将低4位清零,得到16的整数倍。
图例解析
以 x = 8 为例:
- 原始大小:8 字节。
- 加15:8 + 15 = 23(二进制 0000 0000 0001 0111)。
- 取反15:~15 = 1111 1111 1111 0000。
- 按位与:
为什么要加15
确保任何余数(1~15)都能通过进位达到下一个16的倍数。例如:
若 x = 1 → 1 + 15 = 16 → 直接对齐。
若 x = 17 → 17 + 15 = 32 → 对齐到32字节。
为什么用按位与
通过清零低4位(~15 的低4位为0),强制将结果对齐到16字节边界。
由上述我们可以得出alloc方法的源码大概实现流程:
其他
这段代码是C++模板类Zone的一个特化版本,专为布尔模板参数true设计,提供基于C标准库的简单内存管理。其中的alloc() 方法是通过 ::calloc 分配一块大小为 sizeof(T) 的内存,并初始化为零值。
calloc 的特点:分配内存并清零(适合需要初始化的场景)。其返回 void*,需强制转换为 T*。
reinterpret_cast 的作用:将 void* 转换为 T*,直接返回原始内存地址。
从这里我们可以知道alloc方法只适用于T类型(平凡类型),如int、struct{int x;},而且比较适用于需要快速分配且零初始化的内存(如高频创建的临时对象)。
注意:
若T是非平凡类型(含构造函数/析构函数),跳过构造函数会导致未定义行为(UB)
若T对齐要求高于16字节,calloc可能无法满足(但Darwin系统默认对齐到16 字节)
未定义行为:是指程序的行为不可预测,可能表现为崩溃、数据损坏、安全漏洞等。编译器无需对 UB 情况做任何处理,甚至可能优化掉相关代码。
关于构造函数与析构函数,笔者之前发过:【C++】构造函数与析构函数浅知
总结
笔者初次进行源码阅读,学习重点总是捉摸不清,读起来比较费时间,也比较难读懂,本篇文章好多地方还没完善,若有错误,还请斧正,后续笔者将会继续对obj838源码进行阅读解析。
相关文章:
【iOS】OC源码阅读——alloc源码分析
文章目录 前言基本调试方法allocalloc函数逐步调试空类检查快速路径:默认内存分配慢速路径:自定义内存分配slowpath和fastpath alloc核心操作cls->instanceSize:计算所需内存大小内存字节对齐原则为什么要16字节对齐内存字节对齐总结 其他…...
[JavaScript]对象关联风格与行为委托模式
对象关联. “[[prototype)]的机制就是存在于对象中的一个内部链接,它会引用其它对象” 为何创建原型链(关联)? Object.create()会创建一个新对象,参数对象会作为新对象的__proto__. “我们并不需要类来创建两个对象之间的关系,只需要通过委托来关联对象就足够了.而Object.c…...
在 Ubuntu 24.04 LTS 一台机子上同时部署Dify 1.3.1 和 RAGflow 0.18.0
一、RAGflow 0.18.0 简介 有关 Dify 的简介,可以查看我之前分享的 《在 Ubuntu24.04 LTS 上 Docker Compose 部署 Dify 社区版 1.0.1》文章。RAGFlow是一款基于深度文档理解(deepdoc)构建的开源 RAG引擎。其中,深度文档理解&#…...
小熊派BearPi-Pico H3863(二)环境配置 Ubuntu编译源码与VSCode远程开发指南
BearPi-H3863 Ubuntu编译源码与VSCode远程开发指南 摘要开发环境配置方案选型环境部署实战手册一、基础环境配置1. 镜像准备2. 虚拟机初始化3. 网络异常处理 二、VSCode远程开发配置1. SSH服务验证2. VSCode插件安装3. 远程连接实战4. 项目管理 关键要点总结 摘要 本文针对Bea…...
组装 (DIY) 一台显示器 (4K 屏支持 4 画面分屏 PBP 1080p x4)
首发日期 2025-04-26, 以下为原文内容: 家里的 PC 主机比较多, 如果同时开机, 显示器就不够用了. 因为穷, 窝租住的房间又很小, 放不下很多显示器. 所以, 窝希望买一台支持 分屏 功能的显示器. 最好是 4K 分辨率 (3840x2160) 的屏幕, 然后 4 分屏 (有 4 个 DP 或 HDMI 输入接口…...
SwiftUI 8.List介绍和使用
SwiftUI 的 List 组件用于展示可滚动的内容集合,支持静态或动态数据、交互操作(如点击、滑动删除)、分组、自定义样式等。以下是其详细介绍及使用方法: 一、基本用法 1. 静态列表 直接声明固定内容: struct Content…...
Android Kotlin ViewModel 错误处理:最佳 Toast 提示方案详解
在 Android Kotlin 的 ViewModel 中显示 Toast 提示需要特殊处理,因为 ViewModel 不应该直接持有 Context(避免内存泄漏),且 UI 操作(如 Toast)必须在主线程执行。以下是几种标准解决方案: 方案…...
Vue 集成 wangEditor5 公式编辑器的实现步骤
Vue 集成 wangEditor5 公式编辑器的实现步骤 1. 安装公式依赖库2. 配置公式编辑器插件3. 启用工具栏公式按钮4. 组件模板与事件绑定功能验证与调试注意事项版本兼容性: 1. 安装公式依赖库 安装 KaTeX 或 kityformula:根据项目需求选…...
go语言八股文(五)
1.go的局部变量是分配在栈上还是在堆上 在Go语言中,局部变量的内存分配(栈或堆)由编译器基于逃逸分析(escape analysis)来决定。以下是总结和具体示例: 栈上分配 当局部变量的生命周期严格限定在函数作用…...
C++ 解决一个简单的图论问题 —— 最小生成树(以 Prim 算法为例)
使用 C 解决一个简单的图论问题 —— 最小生成树(以 Prim 算法为例),并且使用 Graphviz 库来生成结果图。 在图论中,“边权之和最小” 是最小生成树(MST)的核心目标,其含义和背景可以从以下几个…...
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介 0. 前言1. OpenCV 安装与配置1.1 安装 Python-OpenCV1.2 配置开发环境 2. OpenCV 基础2.1 图像读取与显示2.2 图像保存 3. 摄像头实时捕获小结系列链接 0. 前言 OpenCV (Open Source Computer Vision …...
pgrep和pkill命令详解
pgrep 与 pkill 命令详解 一、基础功能 命令作用核心机制pgrep根据条件查找进程ID (PID)通过进程名、用户、终端等属性筛选进程,输出匹配的PID列表pkill根据条件终止进程向符合条件的进程发送信号(默认发送SIGTERM,可指定其他信号&am…...
Python----卷积神经网络(卷积为什么能识别图像)
一、卷积的概念 卷积是一种数学运算,通常用于信号处理和图像分析。在卷积神经网络中,卷积操作用于提取输入数据(如图像)中的特征。通过将输入数据与卷积核(滤波器)进行卷积运算,CNN能够识别图像…...
web3.js 和 ethers.js 的核心区别
1. 核心设计理念 ---------web3.jsethers.js开发背景以太坊基金会官方维护独立开发者创建,社区驱动架构风格集中式对象 (web3 为核心)模块化设计(分离 Wallet/Provider/Contract)包体积较大(1MB)更轻量(压…...
Atcoder Help 有关Atcoder 的介绍-1 涨分规则
AtCoder 的 Rating 计算系统基于改进的 Elo 算法,主要包含以下核心机制: 一、基础计算公式 Rating 是「表现分(Performance)」的加权平均值减去衰减函数 f ( n ) f(n) f(n),其中: 新用户初始 f ( 1 ) 1200 f(1)1200 f(1)120…...
Android Studio 中使用 SQLite 数据库开发完整指南(Kotlin版本)
文章目录 1. 项目准备1.1 创建新项目1.2 添加必要依赖 2. 数据库设计3. 实现数据库3.1 创建实体类 (Entity)3.2 创建数据访问对象 (DAO)3.3 创建数据库类 4. 创建 Repository5. 创建 ViewModel6. 实现 UI 层6.1 创建笔记列表 Activityactivity_notes_list.xmlNotesListActivity…...
K8S学习笔记01
是什么 高可用,可扩展,自动化,容器化,管理多容器 组件 master API server controller manager scheduler etcd node 对应一台机器 负责运行和托管容器化 kubelet container runtime kube-proxy pod 同一个pod内的容器…...
奥威BI+AI数据分析解决方案
在数字化时代,数据已成为企业决策的核心驱动力。随着大数据、云计算、人工智能等技术的快速发展,企业对数据分析的需求日益迫切。奥威BI(Business Intelligence)与AI(Artificial Intelligence)的结合&#…...
第36课 常用快捷操作——用“鼠标右键”退出当前命令
概述 在AD 20软件中,很多的命令都是可以一直连续下去的,比方说放置一个元器件符号,如果你当中不取消的话,那就可以一直执行下去,放完一个接着放下一个,放完一个接着放下一个…… 想要退出这种连续进行的命…...
用Java模拟打字:深入解析 java.awt.Robot 的键盘控制艺术
作为开发者,我们有时会遇到需要自动化用户界面交互的场景,比如自动化测试、脚本编写、或者制作一些辅助工具。而模拟键盘输入,尤其是“打字”,是这类自动化任务中非常基础且常见的一环。 在 Java 中,实现这一目标的利…...
基于STM32、HAL库的ATSHA204A安全验证及加密芯片驱动程序设计
一、简介: ATSHA204A是Microchip公司生产的一款高性能加密认证芯片,主要特性包括: 基于SHA-256哈希算法的安全认证 4.5KB EEPROM存储空间(可配置为密钥存储、OTP区域等) 唯一的72位序列号 支持I2C和单线接口 工作…...
2.2.1goweb内置的 HTTP 处理程序
net/http 使用源码分析 在 Go 语言的 HTTP 服务器里,HTTP handler 是实现了http.Handler接口的对象。该接口定义如下: type Handler interface {ServeHTTP(ResponseWriter, *Request) }ServeHTTP方法接收两个参数: http.ResponseWriter&am…...
vscode以管理员身份运行报错
1. 问题现象 对vscode设置了管理员权限,但是打开文件时报错或闪退。 2. 解决方法 可以看一下官方网址:[Visual Studio Code on Windows](https://code.visualstudio.com/docs/setup/windows#_unable-to-run-as-admin-when-applocker-is-enabled) 2.1 …...
【Unity】 Dropdown默认选择不选择任何选项
你需要新建一个text文本并将其拖入Placeholder里面,这样你就可以在代码里面设置value-1了,从而实现默认为空...
gem5教程 第七章 如何在 gem 5 中运行我自己的程序
首先,您必须决定是否运行完整系统(FS)或系统调用仿真(SE)。 在 gem5 仿真器中,“完整系统仿真(Full System Simulation, FS)”与“系统调用仿真(System Call Emulation, SE)”是两种不同的仿真模式,各自有其特点和适用场景。下面是对这两种模式的比较: 1. 完整系统仿…...
Java实现基数排序算法
1. 基数排序原理图解 基数排序是一种非比较的排序算法,其核心思想是通过将整数按位数切割成不同的数字,然后按每个位数分别比较。具体步骤如下: 1. 确定最大值:找到数组中的最大值,以确定需要处理的位数。 2. 分配到桶…...
Python项目-支持自然语言处理
研究生组-自然语言处理-第一章节 Python学习,数据挖掘基础 项目地址:pythonbook: 人工智能实战——从 Python 入门到机器学习...
科技助力防灾减灾:卫星电话走进应急救援队伍
在自然灾害与突发事件频发的当下,通信保障已成为应急救援的“生命线”。传统地面通信网络易受极端天气、地形环境等因素制约,而卫星通信技术的突破,尤其是国产天通卫星系统与北斗系统的成熟应用,正推动救援通信体系迈入全天候、无…...
Android adb 安装应用失败(安装次数限制)
adb安装应用失败 前言平台安装失败现象解决 前言 Android Debug Bridge (ADB) 是一个功能强大的命令行工具,用于与 Android 设备通信。 安装 APK 文件: 使用命令 adb install <apk文件路径> 可以将 APK 文件安装到设备上。如果需要覆盖安装&…...
100天精通Python挑战总览 | 零基础到应用实战!
目录 ✨ 为什么发起100天挑战?✨整体学习路线规划第一阶段|基础篇(第1天 - 第50天)第二阶段|应用篇(第51天 - 第100天)Web开发篇爬虫篇数据分析篇AI入门篇 🏆为什么这么划分…...
预训练大模型与元训练大模型在医疗AI项目中的选型对比分析
简要版: 以下是对预训练大模型与元训练大模型(基于元学习/Meta-Learning)在医疗AI项目中选型对比的总结表格: 对比维度预训练大模型元训练大模型(基于元学习)技术基础基于海量通用数据预训练,通过微调适配具体任务(如GPT-4、LLaMA)通过元学习框架训练,支持快速适应新…...
【JavaScript】相等运算符、条件运算符
1、相等运算符 (1)(相等) 相等运算符用来比较两个值是否相等,如果相等会返回true,否则返回false <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"…...
企业用电管理革新利器 —— Acrel-3000 电能管理系统应用解析
电能,以其方便传输、易于转换、便于控制等特性,早已成为广大企事业单位生产、办公的核心能量来源。在 “双碳” 战略目标的宏大背景下,能源结构转型加速推进,电能清洁、高效、零排放的特点愈发凸显。在能源消费侧,“以…...
学生管理系统审计
1.环境搭建 项目地址: https://gitee.com/huang-yk/student-manage 项目下载到本地后IDEA打开,等待项目加载 配置Maven,修改数据库配置文件 然后启动 访问 2.代码审计 1.垂直越权未授权敏感信息泄露 找到拦截器看看对登录做了什么校验 Override public b…...
OpenGL----OpenGL纹理与纹理缓存区
在现代计算机图形学中,纹理(Texture)是一个至关重要的概念。它不仅可以为几何体表面添加细节和真实感,还可以用于实现各种复杂的视觉效果和数据处理。在OpenGL中,纹理的应用范围非常广泛,从基本的颜色映射到高级的阴影映射、环境映射等。本文将深入探讨OpenGL纹理与纹理缓…...
QT开发技术【qcustomplot 曲线与鼠标十字功能】
一、效果 二、代码 #include "obsersingle.h" #include "ui_obsersingle.h" #pragma execution_character_set("utf-8")右键菜单acion回调 // 适应窗口大小 void ObserSingle::RescaleActionFun::fun(ObserSingle *form) {// 自适应y轴数据范围…...
[特殊字符] 大模型后训练指南:从毛坯引擎到智能助手的进化之路 [特殊字符]️
最近看了MIT 6.S191 2025这个讲座感觉讲的挺好的,然后写了一篇总结,大家感兴趣的话可以直接看视频,链接我放到文章最后。 🎯 讲座核心 这个讲座主要讲的是,当我们有了一个基础的大语言模型(就像刚出厂的毛…...
厚铜pcb生产厂家哪家好?
在为您的项目选择厚铜PCB供应商时,技术实力、生产经验与交付能力是决定产品可靠性的关键。随着新能源汽车、工业电源、5G通信等领域对高电流承载、高效散热的需求激增,厚铜PCB(铜厚3oz以上)的工艺门槛不断提升。本文结合行业头部企…...
【重走C++学习之路】22、C++11语法
目录 一、列表初始化 1.1 {}初始化 1.2 std::initializer_list 二、变量类型推导 2.1 auto 2.2 decltype 三、右值引用和移动语义 3.1 左值与左值引用 3.2 右值与右值引用 3.3 左值引用与右值引用比较 3.4 右值引用使用场景和意义 3.5 move 3.6 完美转发和万能引…...
Spring Security授权管理
授权是Spring Security的核心功能之一,是根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则可正常访问,没有访问的权限时则会被拒绝访问。认证是为了保证用户身份的合法性,而授权则是为了更细粒度地对隐私数据进行划分…...
2025A卷-正整数到Excel编号之间的转换
题目描述 用过 excel 的都知道excel的列编号是这样的: a b c … z aa ab ac … az ba bb bc … yz za zb zc … zz aaa aab aac … 分别代表以下编号: 1 2 3 … 26 27 28 29 … 52 53 54 55 … 676 677 678 679 … 702 703 704 705 … 请写个函数&…...
算法设计与分析(期末试卷)
目录 一、频度计算(15 分) 二、项目工期问题(20 分) 三、TSP 问题的贪心算法(15 分) 四、“秤心如意”(15 分) 五、工作指派问题(20 分) 六、计算复杂度…...
springboot(2.6.13)自定义用户授权管理
1.自定义用户访问控制 a.重写configure(HttpSecurity http)方法 在自定义配置类SecurityConfig中重写 Override protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/deta…...
JavaWeb:vueaxios
一、简介 什么是vue? 快速入门 <!-- 3.准备视图元素 --><div id"app"><!-- 6.数据渲染 --><h1>{{ msg }}</h1></div><script type"module">// 1.引入vueimport { createApp, ref } from https://unpkg.com/vu…...
uniapp常用
1.下载文件带进度提示 <template> <view> <button click"startDownload">下载文件</button> <progress :percent"progress" stroke-width"3" /> </view> </template> <…...
etcd 的安装及使用
介绍 Etcd 是一个 golang 编写的分布式、高可用的一致性键值存储系统,用于配置共享和服务发现等。它使用 Raft 一致性算法来保持集群数据的一致性,且客户端通过长连接 watch 功能,能够及时收到数据变化通知,相较于 Zookeepe…...
uni-app vue3 实现72小时倒计时功能
功能介绍 ,数组项有一个下单时间 ,比如今天下单在72小时内可以继续支付,超过则默认取消订单 页面按钮处 加上倒计时 <!-- 倒计时 --> <text v-if"item.timeLeft > 0">{{ formatTime(item.remaining) }}</text&g…...
【C语言】初阶算法相关习题(二)
个人主页:夜晚中的人海 文章目录 ⭐一、两数之和🏠二、珠玑妙算🎡三、寻找奇数🚀四、截取字符串🎉五、寻找峰值 ⭐一、两数之和 题目描述:两数之和 解题思路: 1.先创建一个动态分配的数组ret&a…...
Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理
Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理 目录 Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理 一、简单介绍 二、Flutter 和 Android 原生之间的数据…...
STM32的SysTick
SysTick介绍 定义:Systick,即滴答定时器,是内核中的一个特殊定时器,用于提供系统级的定时服务。该定时器是一个24位的递减计数器,具有自动重载值寄存器的功能。当计数器到达自动重载值时,它会自动重新加载…...