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) 添加一个物理物体…...

Splatter Image运行笔记
文章标题:Splatter Image: Ultra-Fast Single-View 3D Reconstruction 1. 环境配置 下载Splatter Image代码 git clone https://github.com/szymanowiczs/splatter-image.git 创建环境 conda create --name splatter-image python3.8 激活环境 conda activat…...

python爬虫--某房源网站验证码破解
文章目录 使用模块爬取目标验证码技术细节实现成果代码实现使用模块 requests请求模块 lxml数据解析模块 ddddocr光学识别 爬取目标 网站验证码破解思路是统一的,本文以城市列表为例 目标获取城市名以及城市连接,之后获取城市房源信息技术直接替换地址即可 验证码 技术…...

Micropython编译ESP32C3开发板版本过程详细步骤步骤
一、环境说明 开发板:合宙ESP32-C3 工作机器CPU:AMD64 操作系统:Windows10 2004(19041.508) 使用WSL2安装Linux系统 Linux:Ubuntu 24.04.1 LTS python:python 3.12.3(Windows和…...

【开源免费】基于SpringBoot+Vue.JS大创管理系统(JAVA毕业设计)
博主说明:本文项目编号 T 081 ,文末自助获取源码 \color{red}{T081,文末自助获取源码} T081,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…...

mysql 和 tidb的区别
MySQL 和 TiDB 是两种常见的关系型数据库管理系统,但它们的设计理念和适用场景有显著区别。以下从架构、性能、扩展性、适用场景等方面进行对比: 架构设计 MySQL 单机架构为主,可通过主从复制实现读写分离或高可用。分布式支持依赖外部组件&…...

传输层5——TCP可靠传输的实现(重点!!)
TCP协议如何实现可靠传输?确保接收方收到数据? 需要依靠几个结构: 以字节为单位的滑动窗口 这其中包括发送方的发送窗口和接收方的接收窗口 下面的描述,我们指定A为发送端口,B为接收端口 TCP的可靠传输就是靠着滑动窗口…...

基于Python实现web网页内容爬取
文章目录 1. 网页分析2. 获取网页信息2.1 使用默认的urllib.request库2.2 使用requests库1.3 urllib.request 和 requests库区别 2. 更改用户代理3. BeautifulSoup库筛选数据3.1 soup.find()和soup.find_all() 函数 4. 抓取分页链接参考资料 在日常学习和工作中,我们…...

Centos7和9安装mysql5.7和mysql8.0详细教程(超详细)
目录 一、简介 1.1 什么是数据库 1.2 什么是数据库管理系统(DBMS) 1.3 数据库的作用 二、安装MySQL 1.1 国内yum源安装MySQL5.7(centos7) (1)安装4个软件包 (2)找到4个软件包…...

星闪WS63E开发板的OpenHarmony环境构建
目录 引言 关于SDK 安装步骤 1. 更新并安装基本依赖 2. 设置 Python 3.8 为默认版本 3. 安装 Python 依赖 4. 安装有冲突的包 5. 设置工作目录 6. 设置环境变量 7. 下载预构建文件以及安装编译工具 8. 编译工程 nearlink_dk_3863 设置编译产品 编译 制品存放路径…...

MongoDB数据建模小案例
MongoDB数据建模小案例 朋友圈评论内容管理 需求 社交类的APP需求,一般都会引入“朋友圈”功能,这个产品特性有一个非常重要的功能就是评论体系。 先整理下需求: 这个APP希望点赞和评论信息都要包含头像信息: 点赞列表,点赞用户的昵称,头像;评论列表,评论用户的昵称…...