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

代码解析工具cpg

cpg 是一个跨语言代码属性图解析工具,它目前支持C/C++ (C17), Java (Java 13)并且对Go, LLVM, python, TypeScript也有支持,在这个项目的根目录下:

  • cpg-core为cpg解析模块的核心功能,主要包括将代码解析为图,core模块只包括对C/C++/Java的支持。

  • cpg-analysis为基于代码属性图的代码分析规则,比如ValueEvaluator主要基于DFG的回溯遍历计算某一表达式的值。

  • cpg-neo4j将解析结果导入到neo4j数据库。

  • cpg-language-xxx为对xxx语言的支持。

  • cpg-console包含针对用户端的功能,比如bug检测:OutOfBoundsCheck,NullPointerCheck。

cpg将编程语言抽象为1个特性(Trait)集合,语言特性是一组编程语言所共有的特性或特性。任何支持它们的语言都应该实现所需的trait接口。示例可以是对指针的支持、对模板或泛型的支持。

1.Graph Structure

这一部分主要介绍cpg提供的图结构,这些结构旨在提供大多数面向对象语言(如C++、Java或Go)中的语言特性的超集。这包括结构元素,例如函数、方法、类以及表达式/语句,例如调用、运算符、文本或条件。

1.1.Abstract Syntax Tree

树的根是TranslationUnitDeclaration节点,它表示一个文件中包含的代码。树中存在不同类型的AST子节点,每个子节点表示程序中的不同语义:

  • Structural Entities 表示为代码提供其结构的实体。比如代表 namespaces, classes, structs 的结点。

  • Value Declarations 用于建模局部变量、参数、函数、方法和构造函数。

  • Nodes of Program Execution 它为语句和表达式建模。

    • 语句是按顺序执行的语法单元,因此构成命令式程序的程序逻辑。

    • 相比之下,表达式是计算值的语法单位,属于特定的值类型。表达式可以是嵌套的,也可以是语句的子级。

1.2.Control Flow and Evaluation Order

cpg将控制流图(CFG)的概念改编为评估顺序图(evaluation order graph, EOG),它按照语句和表达式被求值的顺序相互连接,以在更细粒度级别上表示控制流。这对于正确捕获来自表达式内部执行顺序的副作用是必要的。可以说EOG是expression-level CFG。

比如对下面代码:

int a = 2 + 3;
a = 0;
a += 1;

EOG为:

请添加图片描述

  • 绿框为3个语句对应的AST根节点,蓝框为其下AST子结点。

  • 蓝线连接同一语句下的AST结点,绿线连接不同语句的AST结点。

可以看出:

  • EOG的连接顺序为AST结点后序遍历顺序

  • 连接的结点都是对应的表达式或者语句访问顺序。

通常,EOG的构造对应后序遍历,当然也存在一些例外情况:

  • 显式更改程序控制流的构造函数,如 if 或其他条件表达式。

  • 表示不按代码出现的顺序执行的代码的节点,例如,在 for (initializer; condition; iteration) body();body();initializer 之后执行,在 iteration 之前执行。

分支语句的根节点在分支表达式(例如条件或选择器)之后和分支目标之前连接,以允许已经遍历分支表达式的算法在必须处理分支之前获得关于语义根的信息。

对于下面分支代码:

if (a == 4)a += 2;
elsea += 3;
return 0;

其EOG如下:

请添加图片描述

1.3.Data Flow

处理数据的操作或实体在CPG内的数据流图(DFG)中表示。要对程序中的数据流进行建模,以下DFG边连接节点:

  • (1).如果父结点的值取决于子结点的值,则子对象包含其父结点的边。比如 BinaryOperator:2 + 3 指向其父结点 VariableDeclaration:a = 2 + 3

  • (2).如果语句对被引用变量进行写入,那么被引用变量是DF edge的起始结点;如果语句读取被引用变量,那么被引用变量是DF edge的开始。比如 a = 1; if (a == 4) xxx 中存在从 DeclaredReferenceExpression: a(a = 1; 中的 a) 指向 BinaryOperator: a== 4 的DF edge。

  • (3).函数调用时会建立从 CallExpression 对应的被引用变量到被调用参数之间的DF edge,以及被调用者定义和该 CallExpression 之间也会建立DF edge,如下面示例所示: DeclaredReferenceExpressionParamVariableDeclaration 之间有数据流,FunctionDeclarationCallExpression 之间也有数据流。

    • 绿边为data flow edge

    • 蓝边为普通AST edge(这里只包含了部分AST信息)

请添加图片描述

  • (4).如果控制流敏感(control-flow-sensitive)的数据流分析被执行,那么对于一个变量 (DeclaredReferenceExpression),在它最后一次被写入的地方和对应引用的位置会有1条数据流

  • (5).对于控制流不敏感的数据流分析,变量引用 (DeclaredReferenceExpression)和变量定义(VariableDeclaration)之间存在数据流。

对于具体DFG建立规则,可以参考cpg DFG

1.4.Additional program semantics

  • 程序和所用语言的类型系统是通过添加其复杂的层次结构作为节点和边来建模的,形成一个类型子图,这有助于通过允许根据细微差别的语言语义进行区分,对语言级语义进行建模,以提高精度。

  • REFERS_TO 连接引用和定义。(每个 DeclaredReferenceExpression 都有1个成员变量refersTo指向对应变量定义的位置)

  • INVOKES 连接调用语句和调用对象。(每个 CallExpression 都有成员变量invokeEdges)指向其可能的调用对象。

2.核心架构和实现

CPG项目由围绕一个库构建的多个工具组成,用于以基于Java/Kotlin的开源实现3的形式对源代码进行迭代图形构建。图1描述了将源代码转换为图形表示的工作流,以及用户对其进行的可视化和分析。

代码解析的核心部分由 cpg-core 完成,用户输入由 cpg-console 完成。

请添加图片描述

2.1.语言前端(Language Frontends)

源代码文件通过其文件扩展名发送到特定语言的前端。然后,前端可以使用针对特定语言的AST解析库解析源代码(针对C/C++使用eclipse CDT,针对Java采用Java Parser)。语言前端应执行以下任务:

  • 特定语言的AST被转换为独立于语言的cpg AST结构,以方便建立独立于特定语言的图结构

  • 隐式存在但未位于源代码中的实体将显式添加到图中,例如隐式 this 字段和缺少的返回语句(void 函数,比如下面代码片段中 swap 函数在解析后补充了 ReturnStatement:return;)

void swap(int *p, int *q) {int t = *p;*p = *q;*q = t;
}int main() {int a = 2, b = 1;swap(&a, &b);int c = a + 1;return 0;
}
  • 标识符被收集在scope tree中,以便以后以模糊的方式解析对名称的访问。在cpg AST的每个结点中,都有一个局部变量scope指向一个Scope对象,每个 scope 对象会用1个ASTNode来标识。以上面代码为例:

    • 整个代码对应的TranslationUnitDeclaration 会对应到一个GlobalScope(记作 globalScope)对象中,该 GlobalScope 对象对应的ASTNode就是该 TranslationUnitDeclaration

    • swapmain 函数对应的 FunctionDeclarationscope 域指向 globalScope

    • swapmain 函数定义下的 CompoundStatement(函数体) 的 scope 域分别指向2个FunctionScope(分别记作 functionScope1, functionScope2),functionScope1, functionScope2 对应的ASTNode分别为2个 FunctionDeclaration 结点

    • int t = *p;, int c = a + 1;scope 域分别指向2个BlockScope,这2个 BlockScope 对应的ASTNode分别为2个函数定义下的 CompoundStatement

cpg-core 中,已经实现了针对C/C++/Java的前端,而 cpg-language-xxx 实现了针对xxx语言的前端。

2.2.ScopeManager

在大多数编程语言中,名称的声明不是全局有效的,但其有效性仅限于与语言构造相关的区域,例如类或函数。这个有效区域被称为作用域(scope)。当前端遍历AST节点时,作用域管理器跟踪当前活动的作用域堆栈。这允许按绝对或相对名称跟踪和解析声明,并管理绑定到封闭语言功能(例如循环、try 语句)范围的控制流跳转。在语言前端构建作用域之后,作用域管理器持有多个作用域树。

在全局存在一个ScopeManager对象,通过 HashMap 的方式将ASTNode映射为 Scope

2.3.Passes

cpg前端产生部分连接的AST树。然后,通过隐式执行信息和程序语义(如使用引用、数据流和求值顺序),使用Passes来丰富cpg。
比如:

  • DFGPass负责生成DFG。

  • ControlFlowSensitiveDFGPass负责生成control-flow sensitive DFG。

  • EvaluationOrderGraphPass负责生成EOG。

这些语义是在独立于语言的AST节点之间构建的,并且它们本身独立于特定编程语言。然而,它们仍然允许特定语言的定制。

当需要graph中的语义时,某些 Pass 取决于其他 Pass 的先前执行。比如 ControlFlowSensitiveDFGPass 依赖于 DFGPass, EvaluationOrderGraphPass。后2者只遍历了AST,而 ControlFlowSensitiveDFGPass 还需遍历EOG。

最后,Pass 也支持推理。对于在源代码中不直接可见的实体,节点将被添加并标记为 IMPLICIT,如果缺少源代码,则为 INFERRED

3.程序分析

cpg在 cpg-analysis 下定义了一些程序分析规则,包括计算表达式的值、不可达代码分析等等。基本是通过图的遍历实现的,这里就介绍以下表达式求值。

表达式求值有点类似于常量传播,不过区别在于这里是通过Data Flow Graph的遍历实现,对应的代码为 ValueEvaluator.evaluate,具体规则参考evaluateInternal函数(还有1个更高级的版本MultiValueEvaluator):

  • 返回值主要为常量值或者 canNotResolve,如果不能确定值的变量,那么返回的可能就是 canNotResolve

  • 如果访问的AST结点为 Literal类型,那么直接返回其值。

  • 如果是 DeclaredReferenceExpression,那么沿着DFG回溯,这里需要注意的是,data flow必须唯一,如果有多个DFG边指向该变量引用,也就是该变量可能值有多个,那么返回 canNotResolve

  • 对于算术运算表达式,则先分别计算其左右值,如果不是 canNotResolve,那么直接计算其值。

4.Bug检测

这一部分为cpg的部分用户功能,放在 cpg-console 模块中。

cpg目前支持2种类型的bug检测,out of bound和空指针访问,这2种bug clang static analyzer(CSA)已有实现,不过CSA基于符号执行,cpg基于data flow graph的反向遍历。

4.1.Out of Bound Check

CSA中的实现可参考知乎介绍,clang对应的代码为ArrayBoundChecker,ArrayBoundCheckerV2。

可以检查出由数组访问造成的溢出读写,比如 array[idx] = 1;,但是数组访问必须满足以下条件:

  • idx 必须是常量表达式(索引可以用变量,但是其值必须是常量)

  • 数组长度必须是常量,且长度通过 new Type[n]; 定义,n 为常量表达式

首先给出以下示例:

#include <iostream>
using namespace std;int main() {int *a = new int[9 + 1];int i = 10;int idx = i + 1;a[idx] = 13;return 0;
}

其中有几个比较重要的AST结点类型:

  • ArrayCreationExpression: 表示由 new Type[n] 组成的AST结点,比如:

请添加图片描述

  • ArraySubscriptionExpression:表示数组访问语句 array[index], arrayindex 都属于 Expression 类(通常为 DeclaredReferenceExpression

请添加图片描述

  • VariableDeclaration: 变量定义结点,在图1中已有示例

  • DeclaredReferenceExpression: 变量引用结点,表示对变量的使用,每个 DeclaredReferenceExpression 都会有一个成员变量 refersTo 指向定义该变量的 VariableDeclaration 结点。比如图2中的 DeclaredReferenceStatement: a 指向图1中的 VariableDeclaration: *a = new int[9 + 1];

检查数组越界访问按以下方式进行,检查对象为 ArraySubscriptionExpression 结点,对于某一个 ArraySubscriptionExpression:

  • 取出改数组表达式的索引(示例中为图2 DeclaredReferenceStatement:idx),计算其值(示例中值为 11),如果不是常量则退出。

  • 找到表达式数组对应的 DeclaredStatementExpression(示例中为图2 DeclaredStatementExpression:a),找到其对应的 VariableDeclaration(示例中为图1 VariableDeclaration: *a = new int[9 + 1];),查找有没有 ArrayCreationExpression,没有则退出(int a[100]; 这种语句都不行)。

  • Type[n] 中的 n 对应着数组长度表达式,计算其值(示例中为 10),不是常量则退出。

  • 比较索引和长度的值,如果索引 >= 长度则报出越界访问。

参考第3部分,表达式的计算核心是回溯DFG,对于计算索引 idx 的值,上述示例比较重要的DFG包括下面4个,计算的过程是从最后1个data flow往前回溯

  • VariableDeclaration:i = 10 --------> DeclaredReferenceExpression:i,其中 VariableDeclaration:i = 10 对应的 initializerLiteral: 10,因此 DeclaredReferenceExpression:i 的结果为 10

  • VariableDeclaration:idx = i + 1 --------> DeclaredReferenceExpression:idx (从语句 int idx = i + 1; 指向 a[idx] = 13;),计算idx时,追溯到 VariableDeclaration:int idx = i + 1,对应的 initializerBinaryOperator: i + 1,左值为 DeclaredReferenceExpression:i,右值为 Literal:1,递归回溯后,左值结果为 10,因此 DeclaredReferenceExpression:idx 的值为 11

没有用到的data flow包括:

  • Literal:10 --------> VariableDeclaration:i = 10

  • BinaryOperator:i + 1 --------> VariableDeclaration:idx = i + 1

同理,可以计算出 a 的长度为 10,因此存在越界访问。

4.2.Null Pointer Check

CSA中的实现可参考NullabilityChecker, GoSSIP团队也在CSA的基础上实现了新的空指针解引用检测算法NewDereferenceChecker。

在cpg中空指针的检测规则比较简单,如果出现指针访问(数组,成员变量,成员方法),对其对应指针变量 base 进行求解,如果可能为 nullptr(必须由 nullptr 初始化,NULL 和默认初始化都不行)。

求解是对 base 变量所有的DFG前驱进行求解,下面示例也会检测出 s->i = 1; 存在空指针访问,这是由于存在错误数据流 VariableDeclaration:*s = nullptr --------> DeclaredReferenceExpression:s(line 11)

struct S1 {char c1; //1个字节int i;   //4个字节char c2; // 1个字节
};int main() {struct S1 *s = nullptr; // 可以识别nullptr关键字,NULL不行s = new S1();s->i = 1;return 0;
}

5.参考文献

paper地址

@article{Weiss_A_Language-Independent_Analysis_2022,author = {Weiss, Konrad and Banse, Christian},doi = {10.48550/arXiv.2203.08424},title = {{A Language-Independent Analysis Platform for Source Code}},year = {2022}
}

相关文章:

代码解析工具cpg

cpg 是一个跨语言代码属性图解析工具&#xff0c;它目前支持C/C (C17), Java (Java 13)并且对Go, LLVM, python, TypeScript也有支持&#xff0c;在这个项目的根目录下: cpg-core为cpg解析模块的核心功能&#xff0c;主要包括将代码解析为图&#xff0c;core模块只包括对C/C/Ja…...

Linux虚拟机部署Java环境-Jdk-Mysql

Linux虚拟机部署 author hf 1.安装 电脑安装x-shell工具&#xff0c;然后使用堡垒机基础控件windows版进行安装扫描&#xff0c;最后点击自动检测&#xff0c;保证能扫描到X-shell工具的安装路径 使用堡垒机登录快照夏选择工具点击Xshell进行连接 查看linux版本 root:~# ca…...

每日学术速递2.9

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV、cs.AI、cs.LG、cs.IR 1.Graph Signal Sampling for Inductive One-Bit Matrix Completion: a Closed-form Solution(ICLR 2023) 标题&#xff1a;归纳单比特矩阵完成的图信号采样&am…...

【Linux】进程优先级 | 进程的切换 | 环境变量详解

&#x1f923; 爆笑教程 &#x1f449; 《看表情包学Linux》&#x1f448; 猛戳订阅 &#x1f525; ​ &#x1f4ad; 写在前面&#xff1a;我们先讲解进程的优先级&#xff0c;探讨为什么会存在优先级&#xff0c;以及如何查看系统进程、进程优先级的修改。然后讲解进程的切…...

leaflet 实现左卷帘效果 (代码示例045)

第045个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中实现左卷帘效果,这里主要引用了leaflet-side-by-side这个插件,直接调用的话,CSS方面有些问题,需要自行调整一下。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示例效果配…...

程序的翻译环境和执行环境

程序环境和预处理&#x1f996;程序的翻译环境和执行环境&#x1f996;详解编译链接&#x1f433; 翻译环境&#x1f433; 详解编译过程&#x1f433; 运行环境&#x1f996;预处理详解&#x1f433; 预定义符号&#x1f433; #define&#x1f980; #define 定义标识符&#x1…...

2023最新量化优选股票参考(2.9)

还是周一发的那些股票&#xff08;可以看我周一的文章&#xff09;&#xff0c;安心持仓就好&#xff0c;跑赢指数是大概率的事情&#xff0c;也大概率获得正收益。 其实我知道大家都没法全天一直看盘操作&#xff0c;毕竟要工作&#xff0c;我也是一样&#xff0c;没法一直看盘…...

深眸科技以科技赋能智慧物流搭建,实现周转箱拆垛作业智能化

数字化时代下市场竞争的核心要素转化为科技的竞争&#xff0c;智能化技术的投入是企业占据市场竞争绝对优势的重要支撑。深眸科技凭借轻辙视觉引擎实现周转箱拆垛作业的智能化突破。人力成本增加&#xff0c;企业积极转变特别是在后疫情时代&#xff0c;人力成本迅猛增加&#…...

R数据分析:孟德尔随机化中介的原理和实操二

delta方法 上面的流程跑通之后&#xff0c;对于中介分析&#xff0c;我们需要报告间接效应的估计值和置信区间&#xff0c;还有中介比例的估计值和置信区间&#xff0c;类似下面的这样&#xff1a; 但是其实我们是光跑孟德尔是得不到上面的需要的值的&#xff08;比如间接效应…...

【SQL开发实战技巧】系列(十二):三问(如何对字符串字母去重后按字母顺序排列字符串?如何识别哪些字符串中包含数字?如何将分隔数据转换为多值IN列表?)

系列文章目录 【SQL开发实战技巧】系列&#xff08;一&#xff09;:关于SQL不得不说的那些事 【SQL开发实战技巧】系列&#xff08;二&#xff09;&#xff1a;简单单表查询 【SQL开发实战技巧】系列&#xff08;三&#xff09;&#xff1a;SQL排序的那些事 【SQL开发实战技巧…...

数据库模式(schema)是什么?

在数据库的术语中&#xff0c;模式&#xff08;schema&#xff09;是一个逻辑概念&#xff0c;用于组织数据库中的对象。模式中的对象通常包括表、索引、数据类型、序列、视图、存储过程、主键、外键等等。 模式可以为数据库对象提供逻辑隔离功能&#xff0c;不用应用程序可以…...

出现failed to load steamui.dll如何解决?好的修复方法推荐

当你电脑突然出现failed to load steamui.dll的时候&#xff0c;你是否一脸懵逼&#xff1f;根本不知道发生啥时候&#xff0c;突然就会这样报错&#xff0c;其实造成这个原因&#xff0c;主要是因为问题出在steam上&#xff0c;我们还是有很多种方法可以解决的&#xff0c;今天…...

js 原生事件触发

var event nullevent new Event(input);document.querySelectorAll("input[placeholder点击网址 选择远端数据字典网址]")[0].dispatchEvent(event)...

Nacos安装配置(二)

目录 一、概述 二、Nacos 安装 A&#xff09;Debian11 1&#xff09;软件环境 2&#xff09;下载源码或者安装包 3&#xff09;mysql配置 4&#xff09;启动服务器 B) Debian11 1) 安装JDK 2) 安装Maven 3) 安装Nacos2 4) 修改访问参数&#xff08;/conf/applicati…...

【Linux基础知识】

Linux基础知识 Linux基础知识 系统目录结构 /bin&#xff1a; 命令和应用程序。 /boot&#xff1a; 这里存放的是启动 Linux 时使用的一些核心文件&#xff0c;包括一些连接文件以及镜像文件。 /dev &#xff1a; dev 是 Device(设备) 的缩写, 该目录下存放的是 Linux 的外…...

【王道数据结构】第七章| 查找 | 树

目录 一、查找 1、查找概念 2、顺序查找 3、折半查找 4、分块查找 二、树 1、B树 2、B树的基本操作 3、B树 4、散列查找及其性能分析 5、散列查找及性能分析 一、查找 1、查找概念 查找&#xff1a;在数据集合中寻找满足某种条件的数据元素的过程称为查找。查找…...

VBA提高篇_19 可选参数Optional_ IsMissing _MSgbox

文章目录1. 可选参数Optional2.IsMissing判断参数是否提供,只能判断变体类型3. 使用 : 可以按参数名传递参数 a:1,c:34.Msgbox 常用参数5.VBA颜色常量表1. 可选参数Optional Optional 代表本参数是可选项 False ; 代表参数若不指定,则默认为False Function mySumProduct(r As R…...

【子网划分】求子网网络前缀、子网地址、每个子网可以分配给主机使用的最小地址和最大地址

1、某单位分配到一个地址块152.7.77.0/24&#xff0c;现在需要进一步划分为4个一样大的子网。&#xff08;10分&#xff09; 问题&#xff1a; (1) 每个子网的网络前缀有多长&#xff1f; (2) 每一个子网中有多少个地址&#xff1f; (3) 每一个子网的网络地址是什么&#xff1f…...

网络协议安全

网络协议安全网络协议ISO/OSI七层模型OSI模型与TCP/IP模型网络接口与互联网层安全传输层与应用层安全传输层协议-TCP协议传输层协议-UDP协议网络协议 ISO/OSI七层模型 物理层 作用&#xff1a;定义物理链路的前期、机械、通信规程、功能要求等将比特流庄换成电压典型物理层设备…...

ImportError: /lib64/libm.so.6: version `GLIBC_2.23‘ not found问题解决方法

1.环境&#xff1a;Centos7&#xff0c;GCC version 9.1.0&#xff0c;python3.7&#xff0c;TensorFlow1.14.0.因为/usr/lib64/libstdc.so.6: version CXXABI_1.3.8 not found问题&#xff0c;我将GCC版本升级到了9.1.0&#xff0c;但是运行TensorFlow的时候出现了ImportError…...

盂县基本情况

寒假的活动报告&#xff0c;万物皆可CSDN&#xff0c;贴一下吧 盂县隶属于阳泉市&#xff0c;阳泉市是李彦宏和刘慈欣的家乡&#xff0c;阳泉市内有百度云计算中心 基本情况 盂县&#xff0c;隶属山西省阳泉市&#xff0c;地处山西省东部、太行山西麓&#xff0c;东与河北省平…...

VC++打开或关闭目标进程的声音(扬声器)(附源码)

VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&a…...

LeetCode 每日一题 2023/1/23-2023/1/29

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录1/23 2303. 计算应缴税款总额1/24 1828. 统计一个圆中点的数目1/25 1632. 矩阵转换后的秩1/26 1663. 具有给定数值的最小字符串1/27 2309. 兼具大小写的最好英文字母1/28 16…...

Hadoop组件Yarn常见命令

Hadoop组件Yarn常见命令 一、概述 当我们不能使用ResourceManager Web UI时,就需要使用Yarn命令来处理问题。因此,我们需要了解如何使用yarn命令监控YARN集群。 Hadoop的yarn命令具有广泛的使用范围: 它可以帮助我们管理大量的MR、Spark、Flink任务。例如获取和杀死正在运…...

QT之事件系统

QT之事件系统1. 概述2. 事件的传递3. 事件类型4. 事件处理与事件过滤5. 自定义事件5.1 Demo6. 发送事件7. 参考1. 概述 在QT中&#xff0c;事件均派生自QEvent抽象类&#xff0c;事件可以由任何派生自QObject的子类实例接收和处理。它们与widget关联性极强。 2. 事件的传递 …...

Python中__init__.py文件深入理解

Python中文件__init__.py深入理解1. 简介1.1 模块&#xff08;Module&#xff09;和包&#xff08;Package&#xff09;的概念1.2 __init__.py文件简介2. __init__.py内容写法2.1 __init__.py文件内容2.2 __init__.py内容解释1. 简介 1.1 模块&#xff08;Module&#xff09;和…...

Jmeter之实现参数化的不同方式详解

参数化简介 定义&#xff1a;动态的获取、设置或生成数据&#xff0c;是一种由程序驱动代替人工驱动的数据设计方案&#xff0c;提高脚本的编写效率以及编写质量 适用场景&#xff1a;当提交的数据量较大时&#xff0c;每次修改太麻烦&#xff0c;可以使用参数化 本文介绍实现…...

Matlab论文插图绘制模板第76期—半对数刻度折线图(Semilogx和Semilogy)

在之前的文章中&#xff0c;分享了Matlab双对数刻度折线图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下半对数刻度折线图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;Matlab论文插图绘制模板系列&#xff0c;旨在降低大家使用Matlab进行科研…...

【找工作】永善县政务服务管理局公开招聘5名公益性岗位人员

【找工作】永善县政务服务管理局公开招聘5名公益性岗位人员 为贯彻落实《中华人民共和国就业促进法》《就业服务和就业管理规定》&#xff0c;帮助有劳动能力和就业愿望的就业困难人员实现就业&#xff0c;永善县政务服务管理局拟向社会公开招聘公益性岗位人员5名&#xff0c;…...

【C++】从0到1入门C++编程学习笔记 - 提高编程篇:STL常用算法(拷贝和替换算法)

文章目录一、copy二、replace三、replace_if四、swap学习目标&#xff1a; 掌握常用的拷贝和替换算法 算法简介&#xff1a; copy // 容器内指定范围的元素拷贝到另一容器中replace // 将容器内指定范围的旧元素修改为新元素replace_if // 容器内指定范围满足条件的元素替换…...