Linux上的C语言编程实践
说明:
这是个人对该在Linux平台上的C语言学习网站笨办法学C上的每一个练习章节附加题的解析和回答
ex1:
- 在你的文本编辑器中打开
ex1文件,随机修改或删除一部分,之后运行它看看发生了什么。
vim ex1.c打开ex1.c文件。假如我们删除return 0;这一行代码,保存文件后,在命令行中进入该文件所在目录,然后尝试运行程序(执行./ex1命令,前提是之前已经成功编译生成了ex1可执行文件)。
结果:根据 C 语言程序的运行机制,main函数如果没有显式的return语句,在大多数实现中,函数执行结束时会隐式返回一个默认值(通常是0,但这依赖于具体编译器实现)。而在运行时,由于程序逻辑本身没有依赖return值去做进一步操作,所以程序可能依然能够输出Hello world.,看起来好像正常运行了,但从代码规范性角度是存在问题的。
- 再多打印5行文本或者其它比
"Hello world."更复杂的东西。
跳过
- 执行
man 3 puts来阅读这个函数和其它函数的文档。
命令行中会显示puts函数的详细文档信息,包括函数的功能描述(例如它用于向标准输出设备输出字符串,并自动在末尾添加一个换行符)、函数的原型(int puts(const char *s);)、函数的参数说明(s参数是要输出的字符串指针)、函数的返回值含义(成功时返回一个非负整数,出错时返回EOF)等内容。同时,在该手册页中还会列出与之相关的其他一些函数(比如printf、fputs等函数)的简单介绍和参考位置
ex2:
- 创建目标
all:ex1,可以以单个命令make构建ex1。
在 Makefile 里定义了 all 这个目标,并且让它依赖于 ex1,这意味着当执行 make 命令时(如果没有 指定具体目标,默认会执行 Makefile 里的第一个目标或者由 .DEFAULT_GOAL 指定的目标,这里添加 all 目标后通常就会执行它),make 会先检查 ex1 是否需要更新(例如其依赖的 ex1.c 文件是否有修改 等情况),如果需要更新就会执行 ex1 目标下定义的构建命令(即 cc $(CFLAGS) ex1.c -o ex1)来生 成 ex1 文件,这样就实现了通过单个 make 命令来构建 ex1 的功能。CFLAGS=-Wall -gall: ex1clean:rm -f ex1ex1: ex1.ccc $(CFLAGS) ex1.c -o ex1
- 阅读
man make来了解关于如何执行它的更多信息。
跳过
- 阅读
man cc来了解关于-Wall和-g行为的更多信息。
-Wall,会详细说明它启用的具体警告类别,解释不同警告所对应的代码潜在问题类型,比如变量未使用 、类型不兼容、隐式函数声明等各种情况产生的警告。而对于 -g,会讲解它如何在生成的可执行文件中 嵌入调试信息,像调试符号的存储格式、在使用调试工具(如 gdb)时如何利用这些调试信息来定位代码中的问题(例如查看变量值、跟踪函数调用流程等操作如何基于这些调试符号实现)等内容。
- 在互联网上搜索Makefile文件,看看你是否能改进你的文件。
找到文件如下:CC = gcc # 指定编译器 CFLAGS = -Wall -Wextra -g # 执行的make命令的可选选项,-Wall 表示启用所有警告,-Wextra 是额外的警告选项,会进一步给出更多类型的警告信息,-g 选项用于在生成的目标文件中添加调试信息,方便后续使用调试工具(如 gdb)来调试程序 LDFLAGS = -lm # 用于指定链接阶段的选项,-lm 表示要链接数学库(libm) SRC = $(wildcard src/*.c) # 使用 wildcard 函数来查找 src 目录下所有以 .c 为后缀的源文件 OBJ = $(SRC:.c=.o) # 变量替换,将 SRC 变量中每个文件名的后缀 .c 替换为 .o,从而得到对应的目标文件 TARGET = myprogram # 定义了最终要生成的可执行文件的名称为 myprogram.PHONY: all clean # 声明 all 和 clean 为伪目标。伪目标并不对应实际的文件,而是代表一些操作或者规则; 用伪目标可以避免与可能存在的同名文件产生冲突,保证规则正常执行all: $(TARGET) #定义了 all 这个目标依赖于 $(TARGET)$(TARGET): $(OBJ)$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) # $@代表当前规则的目标,这里为$(TRAGET);$^ 表示所有依赖,在这里就是所有的 .o 文件; -o 选项为指定生成文件名称%.o: %.c # 将所有.c 文件依赖.o 文件$(CC) $(CFLAGS) -c -o $@ $< # $< 表示第一个依赖,在这里就是对应的 .c 源文件clean:rm -f $(OBJ) $(TARGET)
- 在另一个C语言项目中找到
Makefile文件,并且尝试理解它做了什么。
在github上找了一个开源的项目nginx/nginx: The official NGINX Open Source repository.的Makefile的,内容如下:# Compiler and linker settings CC = cc CFLAGS = -O2 -pipe -Wall # -O2 一种优化级别选项,它指示编译器对代码进行一定程度的优化,以提高生成的可执行文件的运行效率;-pipe 让编译器在编译过程中使用管道来传递中间结果,这样可以加快编译速度 LDFLAGS = # 用于指定链接阶段的选项,这里为空表示暂时没有额外添加特定的链接相关设置# Targets all: buildbuild:$(CC) $(CFLAGS) -o nginx src/*.c $(LDFLAGS) # src 目录下所有的 .c 源文件进行编译,然后通过 -o nginx 将生成的可执行文件命名为 nginxclean:rm -f nginx *.o # 强制删除名为 nginx 的可执行文件以及所有后缀为 .o 的目标文件
ex3:
- 找到尽可能多的方法使
ex3崩溃。
改变格式化占位符与参数类型不匹配:
将 printf("I am %d years old.\n", age); 中的 %d 改为 %s,像这样 printf("I am %s years old.\n", age);,然后重新编译运行。由于 %s 期望传入的是字符串指针类型的参数,而这里传入的是 int 类型的 age,编译器会给出类型不匹配相关警告。
传入的参数个数少于格式化字符串中占位符个数:
修改 printf 语句为 printf("I am %d years %d old\n", age);,也就是在格式字符串中多写了一个 %d 占位符,但只传入了一个 age 参数。重新编译时,编译器会提示参数数量不足的警告,运行时程序输出结果会是错误的,可能会输出一些随机的数值来填充多余的占位符对应的位置,导致输出不符合预期,甚至可能因非法内存访问等原因而崩溃。
格式化字符串中使用非法的转义序列:
把 printf("I am %d years old.\n", age); 中的 \n 改为比如 \z(\z 不是合法的转义序列),变成 printf("I am %d years old.\z", age);,编译时编译器可能会给出关于非法转义序列的警告。
- 执行
man 3 printf来阅读其它可用的'%'格式化占位符。如果你在其它语言中使用过它们,应该看着非常熟悉(它们来源于printf)。
除了常见的 %d(用于输出十进制整数)、%s(用于输出字符串)外,还有比如:
%f:用于输出浮点数,例如 float num = 3.14; printf("The number is: %f\n", num); 可以将浮点数 num 的值以常规的小数形式输出。
%c:用于输出单个字符,像 char ch = 'A'; printf("The character is: %c\n", ch); 能输出字符 A。
%x 或 %X:分别用于以十六进制小写形式和大写形式输出整数,例如 int hex_num = 255; printf("The hex number is: %x\n", hex_num); 会输出 ff(以小写十六进制展示整数 255 的值),若使用 %X 则会输出 FF。
%o:用于以八进制形式输出整数,如 int oct_num = 10; printf("The octal number is: %o\n", oct_num); 会输出 12(八进制下 10 的表示)。
%p:用于输出指针的值(以十六进制形式展示内存地址),例如 int *ptr = # printf("The pointer address is: %p\n", ptr); 可以输出 ptr 指针所指向的内存地址(十六进制格式)。
手册页里还会介绍每个占位符对应的可选修饰符,比如设置宽度、精度、对齐方式等内容,帮助更灵活准确地进行格式化输出。
- 将
ex3添加到你的Makefile的all列表中。到目前为止,可以使用make clean all来构建你所有的练习。
添加all: ex1 ex3
- 将
ex3添加到你的Makefile的clean列表中。当你需要的时候使用make clean可以删除它。
添加:clean:rm -f ex1 ex3
ex4:
安装 Valgrind说明:
教学网站中的讲义下载Valgrind链接已经失效了,所以使用最新的版本的下载地址
curl -O https://sourceware.org/pub/valgrind/valgrind-3.24.0.tar.bz2
- 按照上面的指导,使用
Valgrind和编译器修复这个程序。
我运行程序错误信息如下:$ valgrind ./ex4 ==19914== Memcheck, a memory error detector ==19914== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al. ==19914== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info ==19914== Command: ./ex4 ==19914== ^[[BI am -16778024 years old. ==19914== Conditional jump or move depends on uninitialised value(s) ==19914== at 0x48D70BB: __printf_buffer (vfprintf-process-arg.c:58) ==19914== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==19914== by 0x48CD1A2: printf (printf.c:33) ==19914== by 0x109188: main (ex4.c:9) ==19914== ==19914== Use of uninitialised value of size 8 ==19914== at 0x48CC0AB: _itoa_word (_itoa.c:183) ==19914== by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) ==19914== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==19914== by 0x48CD1A2: printf (printf.c:33) ==19914== by 0x109188: main (ex4.c:9) ==19914== ==19914== Conditional jump or move depends on uninitialised value(s) ==19914== at 0x48CC0BC: _itoa_word (_itoa.c:183) ==19914== by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) ==19914== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==19914== by 0x48CD1A2: printf (printf.c:33) ==19914== by 0x109188: main (ex4.c:9) ==19914== ==19914== Conditional jump or move depends on uninitialised value(s) ==19914== at 0x48D6D79: __printf_buffer (vfprintf-process-arg.c:186) ==19914== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==19914== by 0x48CD1A2: printf (printf.c:33) ==19914== by 0x109188: main (ex4.c:9) ==19914== I am 31 inches tall. ==19914== ==19914== HEAP SUMMARY: ==19914== in use at exit: 0 bytes in 0 blocks ==19914== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated ==19914== ==19914== All heap blocks were freed -- no leaks are possible ==19914== ==19914== Use --track-origins=yes to see where uninitialised values come from ==19914== For lists of detected and suppressed errors, rerun with: -s ==19914== ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 0 from 0)检测到的问题总结:
Conditional jump or move depends on uninitialised value:“条件跳转或移动操作依赖于未初始化的值”
Use of uninitialised value of size 8:“使用了大小为 8 字节的未初始化值”
这些问题表明某个变量在被正确初始化之前就被使用了,这会导致不可预测的行为
at 0x48CC0AB: _itoa_word (_itoa.c:183)
at 0x48D70BB: __printf_buffer (vfprintf-process-arg.c:58)
by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544)
by 0x48CD1A2: printf (printf.c:33)
by 0x109188: main (ex4.c:9)
表明错误出现在程序(ex4.c)的main函数中(具体在第 9 行),特别是在printf调用期间。 栈追踪信息显示错误源于标准库中的vfprintf-process-arg.c和_itoa.c文件,这表明问题出在printf函数的格式化或参数处理方面。
使用Valgrind调试修复的这个程序:
Use --track-origins=yes to see where uninitialised values come from
这是Valgrind 给出的提示: 使用--track-origins=yes选项来确定未初始化值的确切来源。$ valgrind --track-origins=yes./ex4 valgrind: no program specified valgrind: Use --help for more information. Lin:~/ysyx/ysyx-workbench/learn_record/C_Linux/ex4$ valgrind --track-origins=yes ./ex4 ==21270== Memcheck, a memory error detector ==21270== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al. ==21270== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info ==21270== Command: ./ex4 ==21270== I am -16778024 years old. ==21270== Conditional jump or move depends on uninitialised value(s) ==21270== at 0x48D70BB: __printf_buffer (vfprintf-process-arg.c:58) ==21270== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==21270== by 0x48CD1A2: printf (printf.c:33) ==21270== by 0x109188: main (ex4.c:9) ==21270== Uninitialised value was created by a stack allocation ==21270== at 0x109149: main (ex4.c:4) ==21270== ==21270== Use of uninitialised value of size 8 ==21270== at 0x48CC0AB: _itoa_word (_itoa.c:183) ==21270== by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) ==21270== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==21270== by 0x48CD1A2: printf (printf.c:33) ==21270== by 0x109188: main (ex4.c:9) ==21270== Uninitialised value was created by a stack allocation ==21270== at 0x109149: main (ex4.c:4) ==21270== ==21270== Conditional jump or move depends on uninitialised value(s) ==21270== at 0x48CC0BC: _itoa_word (_itoa.c:183) ==21270== by 0x48D6C8B: __printf_buffer (vfprintf-process-arg.c:155) ==21270== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==21270== by 0x48CD1A2: printf (printf.c:33) ==21270== by 0x109188: main (ex4.c:9) ==21270== Uninitialised value was created by a stack allocation ==21270== at 0x109149: main (ex4.c:4) ==21270== ==21270== Conditional jump or move depends on uninitialised value(s) ==21270== at 0x48D6D79: __printf_buffer (vfprintf-process-arg.c:186) ==21270== by 0x48D872A: __vfprintf_internal (vfprintf-internal.c:1544) ==21270== by 0x48CD1A2: printf (printf.c:33) ==21270== by 0x109188: main (ex4.c:9) ==21270== Uninitialised value was created by a stack allocation ==21270== at 0x109149: main (ex4.c:4) ==21270== I am 31 inches tall. ==21270== ==21270== HEAP SUMMARY: ==21270== in use at exit: 0 bytes in 0 blocks ==21270== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated ==21270== ==21270== All heap blocks were freed -- no leaks are possible ==21270== ==21270== For lists of detected and suppressed errors, rerun with: -s ==21270== ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 0 from 0)Why is the result no different from the command valgrind without --track-origins=yes发现多了一个错误信息 Uninitialised value was created by a stack allocation
at 0x109149: main (ex4.c:4)
Valgrind 指出程序中正在使用一个未初始化的变量。在代码中的特定行(ex4.c文件里有效代码的第 4 行,并且这个错误是在main函数中出现的)包含了一个在栈上分配但在使用前未被初始化的变量。
观察代码文件ex4.c中内容
值得一提的是:在 C 语言代码中,行号计数通常是从 1 开始按顺序依次递增的,这里说的行号计数递增是是从整个源文件的角度去数的有效代码行号(空行不算),也就是包含了前面的头文件引入(#include <stdio.h>算第 1 行)以及main函数的定义那一行(int main()算第 3 行)之后,int height;所在的那一行就是第 4 行了
by 0x109188: main (ex4.c:9)
at 0x109149: main (ex4.c:4)
at部分是在追溯未初始化值的起源,也就是变量在内存中最初分配(创建)的位置。它告诉我们这个未初始化的隐患是从哪里开始的,在这个例子中就是变量height被声明的那一行。 by部分是在指出错误发生的位置,即程序在执行到哪一行代码时,因为使用了这个未初始化的值而触发了错误。这是实际产生错误行为的代码位置。
这里by使用的从代码文本编辑器显示的相对行数角度指的是printf("I am %d inches tall.\n", height);这一行,而错误的起源at使用的从整个源文件绝对行号的角度指的是int height;这一行,根据错误信息Uninitialised value was created by a stack allocation(未初始化值是通过栈分配产生的)给int height赋值从而解决改错误信息。
对于Valgrind 侧重于检测与内存访问相关的错误,例如使用未初始化的内存、无效的内存读 / 写操作或内存泄漏等情况。如果代码包含逻辑错误或与内存访问无关的问题,Valgrind 不会对其进行标记。所以对于printf("I am %d years old.\n");缺少参数的情况我们使用编译器可以轻松检查出错误问题
至此我们通过使用$ make -f ../ex2/Makefile ex4 cc -Wall -g ex4.c -o ex4 ex4.c: In function ‘main’: ex4.c:8:19: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat=]8 | printf("I am %d years old.\n");| ~^| || int ex4.c:5:9: warning: unused variable ‘age’ [-Wunused-variable]5 | int age = 10;| ^~~Valgrind和编译器修复了这个程序。
-
在互联网上查询
Valgrind相关的资料。
Valgrind 官方首页:这里是获取 Valgrind 最新信息的权威来源,包含了 Valgrind 的当前版本、支持的平台、近期新闻等内容。例如,你可以了解到 2024 年 10 月 31 日发布的 Valgrind-3.24.0 版本所支持的众多操作系统和硬件架构等信息 。
Valgrind 官方文档页面:详细介绍了 Valgrind 的各种工具、使用方法、命令行选项等,是深入学习和使用 Valgrind 的必备参考。比如,关于 Memcheck 工具的详细介绍,包括它能够检测的各种内存错误类型,如使用未初始化的内存、内存泄漏等,以及相关的命令行选项如--leak-check的具体用法等都有详细说明.
- 下载另一个程序并手动构建它。尝试一些你已经使用,但从来没有手动构建的程序。
参考如下;# 下载源码的归档文件来获得源码 # 解压归档文件,将文件提取到你的电脑上 # 运行./configure来建立构建所需的配置 # 运行make来构建源码,就像之前所做的那样 # 运行sudo make install来将它安装到你的电脑# 1) Download it (use wget if you don't have curl) curl -O http://valgrind.org/downloads/valgrind-3.6.1.tar.bz2# use md5sum to make sure it matches the one on the site md5sum valgrind-3.6.1.tar.bz2# 2) Unpack it. tar -xjvf valgrind-3.6.1.tar.bz2# cd into the newly created directory cd valgrind-3.6.1# 3) configure it ./configure# 4) make it make# 5) install it (need root) sudo make install
- 看看
Valgrind的源码是如何在目录下组织的,并且阅读它的Makefile文件。不要担心,这对我来说没有任何意义。
Valgrind 的源码目录组织大概是这样的:有 coregrind 目录,这里面包含了它的核心功能实现代码,像内存管理以及错误检测等相关代码,是整个 Valgrind 的核心引擎所在。include 目录存放着 Valgrind 的头文件,定义了各种数据结构、函数接口这些内容,方便其他模块或者外部程序去引用。还有像 memcheck 目录,实现的是 Memcheck 工具的具体逻辑,能检测内存泄漏、越界访问等内存相关错误。cachegrind 目录包含的是 Cachegrind 工具代码,用于分析程序缓存使用情况来辅助优化性能。callgrind 目录里放着 Callgrind 工具相关代码,可分析程序调用图、函数调用关系以及收集相关性能数据。另外有 docs 目录存着文档,像用户手册、技术文档之类的,方便大家了解使用 Valgrind,tests 目录包含各种测试用例,用来测试验证 Valgrind 功能,保证其正确稳定。
Valgrind 是通过运行 “./configure” 命令,能指定像 “--prefix” 设置安装目录、“--host” 指定目标主机类型等参数。“./configure” 运行完就会生成 “Makefile” 文件,这个文件里有编译、链接等构建规则,指导 “make” 命令怎么构建 Valgrind。然后执行 “make” 命令进行编译,按规则把源文件编译成目标文件和可执行文件,最后用 “make install” 命令把编译好的文件安装到指定的安装目录下。
阅读它的 Makefile 文件的话,里面就是那些具体的编译、链接规则,还有依赖关系等内容,不同部分对应不同工具或者功能模块的构建相关设定
相关文章:
Linux上的C语言编程实践
说明: 这是个人对该在Linux平台上的C语言学习网站笨办法学C上的每一个练习章节附加题的解析和回答 ex1: 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后运行它看看发生了什么。 vim ex1.c打开 ex1.c 文件。假如我们删除 return 0…...
芝法酱学习笔记(1.3)——SpringBoot+mybatis plus+atomikos实现多数据源事务
一、前言 1.1 业务需求 之前我们在讲解注册和登录的时候,有一个重要的技术点忽略了过去。那就是多数据源的事务问题。 按照我们的业务需求,monitor服务可能涉及同时对监控中心数据库和企业中心数据库进行操作,而我们希望这样的操作在一个事…...
【计算机网络】实验12:网际控制报文协议ICMP的应用
实验12 网际控制报文协议ICMP的应用 一、实验目的 验证ping命令和tracert命令的工作原理。 二、实验环境 Cisco Packet Tracer模拟器 三、实验过程 1.构建网络拓扑并进行信息标注,将所需要配置的IP地址写在对应的主机或者路由器旁边,如图1所示。 图…...
收缩 tempdb 数据库
1、 本文内容 注解使用 ALTER DATABASE 命令使用 DBCC SHRINKDATABASE 命令使用 DBCC SHRINKFILE 命令运行收缩操作时出现错误 8909 适用于: SQL ServerAzure SQL 托管实例 本文讨论可用于收缩 SQL Server 中 tempdb 数据库的各种方法。 可以使用下列任一方法来…...
kubesphere搭建 postgres15
创建configMap POSTGRES_PASSWORD数据库密码 PGDATA数据目录 创建【有状态副本集】工作负载 1.创建基本信息 2.容器组设置 配置环境变量 3.存储设置 完成之后点击下一步 配置服务 创建服务 配置基本信息 配置服务信息 外部访问选择nodePort,然后点击…...
解决npm问题用到的资源,错误原因和方法
资源: 1.node版本管理工具nvm: 下载地址:https://nvm.uihtm.com/nvm-1.1.12-setup.zip 使用方法:https://nvm.uihtm.com/ 2.node各版本: https://nodejs.org/en/about/previous-releases 3.nodejs: 下载地址:https://…...
【uni-app 微信小程序】新版本发布提示用户进行更新
知识准备 uni.getUpdateManager文档介绍 不支持APP与H5,所以在使用的时候要做好平台类型的判断,如何判断,参考条件编译处理多端差异 代码参考 export const updateApp () > {const updateManager uni.getUpdateManager()updateManag…...
Redis性能优化18招
Redis性能优化的18招 目录 前言选择合适的数据结构避免使用过大的key和value[使用Redis Pipeline](#使用Redis Pipeline)控制连接数量合理使用过期策略使用Redis集群充分利用内存优化使用Lua脚本监控与调优避免热点key使用压缩使用Geo位置功能控制数据的持久化尽量减少事务使…...
ElasticSearch 与向量数据库的结合实践:突破亿级大表查询瓶颈20241204
💡 ElasticSearch 与向量数据库的结合实践:突破亿级大表查询瓶颈 📚 引言 随着业务规模的不断扩大,传统关系型数据库在处理 亿级大表 时,性能瓶颈愈加凸显。关键词检索、模糊查询、多条件筛选等需求逐步升级ÿ…...
C#实现一个HttpClient集成通义千问-流式输出内容提取
返回对象处理 返回对象分析 根据流式返回的数据处理 内容对象 {"choices": [{"delta": { "content": "", "role": "assistant" },"index": 0,"logprobs": null,"finish_reason"…...
微信小程序后台搭建—node+mysql
想必大家都有一个困扰,想要用微信小程序作为前端,但是后端不知道如何用node连接微信小程序,我最近也一直困扰许久,所以我就想用node写后端接口在连接微信小程序,记录一下学习笔记 前言 前端:微信小程序 后端:nodeexp…...
断点续传+测试方法完整示例
因为看不懂网上的断点续传案例,而且又不能直接复制使用,干脆自己想想写了一个。 上传入参类: import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProp…...
C# 中的静态构造函数和实例构造函数的区别
在C#中,静态构造函数和实例构造函数在类的初始化过程中扮演着不同的角色。下面我将详细介绍这两种构造函数的区别: 实例构造函数(Instance Constructor): 实例构造函数用于初始化类的实例(对象)…...
如何在UI自动化测试中创建稳定的定位器?
如何在UI自动化测试中创建稳定的定位器? 前言1. 避免使用绝对路径2. 避免在定位器中使用索引3. 避免多个类名的定位器4. 避免动态和自动生成的ID5. 确保定位器唯一6. 处理隐藏元素的策略7. 谨慎使用基于文本的定位器8. 使用AI创建稳定的定位器 总结 前言 在自动化测…...
【5G】5G技术组件 5G Technology Components
5G的目标设置非常高,不仅在数据速率上要求达到20Gbps,在容量提升上要达到1000倍,还要为诸如大规模物联网(IoT, Internet of Things)和关键通信等新服务提供灵活的平台。这些高目标要求5G网络采用多种新技术…...
四十一:Web传递消息时的编码格式
在现代Web应用中,数据在客户端和服务器之间的传递往往需要经过特定的编码方式。不同类型的数据(如文本、图像、文件等)需要用不同的编码格式进行表示,以确保信息的准确性与安全性。本文将介绍Web传递消息时常用的几种编码格式&…...
【细如狗】记录一次使用MySQL的Binlog进行数据回滚的完整流程
文章目录 1 事情起因2 解决思路3 利用binlog进行数据回滚 3.1 确认是否启用Binlog日志3.2 确认是否有binlog文件3.3 找到误操作的时间范围3.4 登录MySQL服务器查找binlog文件 3.4.1 查询binlog文件路径3.4.2 找到binlog文件3.4.3 确认误操作被存储在哪一份binlog文件中 3.5 查…...
什么是云原生数据库 PolarDB?
云原生数据库 PolarDB 是阿里云推出的一款高性能、兼容性强、弹性灵活的关系型数据库产品。它基于云原生架构设计,结合分布式存储和计算分离的技术优势,为用户提供强大的计算能力、卓越的可靠性以及高性价比的数据库解决方案。PolarDB 适合各种业务场景&…...
Kafka Stream实战教程
Kafka Stream实战教程 1. Kafka Streams 基础入门 1.1 什么是 Kafka Streams Kafka Streams 是 Kafka 生态中用于 处理实时流数据 的一款轻量级流处理库。它利用 Kafka 作为数据来源和数据输出,可以让开发者轻松地对实时数据进行处理,比如计数、聚合、…...
BEPUphysicsint定点数3D物理引擎使用
原文:BEPUphysicsint定点数3D物理引擎使用 - 哔哩哔哩 上一节給大家介绍了BEPUphysicsint的一些基本的情况,这节课我们来介绍它的基本使用,本节主要从以下5个方面来介绍: (1) 创建一个物理世界Space,并开启模拟迭代; (2) 添加一个物理物体…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
