Linux上的C语言编程实践

news2025/5/19 12:42:18

说明:

         这是个人对该在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)等内容。同时,在该手册页中还会列出与之相关的其他一些函数(比如 printffputs 等函数)的简单介绍和参考位置

 

ex2: 

  • 创建目标all:ex1,可以以单个命令make构建ex1
    CFLAGS=-Wall -g
    
    all: ex1
    
    clean:
        rm -f ex1
    
    ex1: ex1.c
        cc $(CFLAGS) ex1.c -o ex1
    在 Makefile 里定义了 all 这个目标,并且让它依赖于 ex1,这意味着当执行 make 命令时(如果没有 指定具体目标,默认会执行 Makefile 里的第一个目标或者由 .DEFAULT_GOAL 指定的目标,这里添加 all 目标后通常就会执行它),make 会先检查 ex1 是否需要更新(例如其依赖的 ex1.c 文件是否有修改 等情况),如果需要更新就会执行 ex1 目标下定义的构建命令(即 cc $(CFLAGS) ex1.c -o ex1)来生 成 ex1 文件,这样就实现了通过单个 make 命令来构建 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: build
    
    build:
        $(CC) $(CFLAGS) -o nginx src/*.c $(LDFLAGS) # src 目录下所有的 .c 源文件进行编译,然后通过 -o nginx 将生成的可执行文件命名为 nginx
    
    clean:
        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 = &num; printf("The pointer address is: %p\n", ptr); 可以输出 ptr 指针所指向的内存地址(十六进制格式)。
    手册页里还会介绍每个占位符对应的可选修饰符,比如设置宽度、精度、对齐方式等内容,帮助更灵活准确地进行格式化输出。
     
  • ex3添加到你的Makefileall列表中。到目前为止,可以使用make clean all来构建你所有的练习。
    添加all: ex1 ex3
     
  • ex3添加到你的Makefileclean列表中。当你需要的时候使用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 文件的话,里面就是那些具体的编译、链接规则,还有依赖关系等内容,不同部分对应不同工具或者功能模块的构建相关设定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2257407.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Fastadmin地图插件在表单中的使用

表单中实现地图选择获取经纬度 1.Fastadmin后台安装地图选择插件地图位置(经纬度)选择插件 - 支持百度地图、高德地图、腾讯地图 – 基于ThinkPHP和Bootstrap的极速后台开发框架 2.腾讯地图开放平台后台创建应用创建KEY&#xff0c;配置逆地址解析额度。插件配置中配置腾讯地图…

Java项目实战II基于微信小程序的电子竞技信息交流平台的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网技术的飞速发展…

计算机网络期末常见问答题总结

1、试说明为什么在运输建立时使用三报文握手&#xff0c;如果不采用三报文握手会出现什么情况&#xff1f; TCP三次握手的目的是确保客户端和服务器都能够接收对方的连接请求,并建立起可靠的连接。如果只进行两次握手,可能会导致以下情况的发生: - 如果客户端发送的SYN包在网…

kubesphere搭建 postgres15

创建configMap POSTGRES_PASSWORD数据库密码 PGDATA数据目录 创建【有状态副本集】工作负载 1.创建基本信息 2.容器组设置 配置环境变量 3.存储设置 完成之后点击下一步 配置服务 创建服务 配置基本信息 配置服务信息 外部访问选择nodePort&#xff0c;然后点击…

【55 Pandas+Pyecharts | 实习僧网Python岗位招聘数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 去除重复数据2.4 调整部分城市名称 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 招聘数量前20岗位3.2 各城市招聘数量3…

/usr/local/go/bin/go: cannot execute binary file: Exec format error

现象&#xff1a;ubuntu中安装go软件环境&#xff0c;报上述错误 原因&#xff1a;系统与软件不适配 解决&#xff1a;查看本系统的版本 找到x86-64对应的go版本即可

记录模板学习(持续更新)

目的&#xff1a; 学习C模板的编写&#xff0c;使用模板类包装一个可调用对象 可调用对象包括&#xff1a;普通函数&#xff0c; lambda表达式&#xff0c; 类成员函数 可以参考到QtConcurrent::run的实现&#xff0c;可以看到这个函数有非常多重载&#xff0c;其中可以接受类…

从0开始边做边学,用vue和python做一个博客,非规范化项目,怎么简单怎么弄,跑的起来有啥毛病解决啥毛病(三)

基础的内容都差不多了&#xff0c;开始研究文章详情页的内容设计&#xff0c;程序员嘛肯定要用markdown编辑了&#xff0c;找了一些发现这个md-editor看着还不错&#xff0c;文档介绍页比较清晰&#xff0c;用着也比较简单。 md-editor安装配置使用Mock.js模拟请求接口mock.js …

Android 逆向/反编译/Hook修改应用行为 基础实现

前言&#xff1a;本文通过一个简单的情景案例实现安卓逆向的基本操作 一、情景描述 本文通过一个简单的情景案例来实现安卓逆向的基本操作。在这个案例中所使用的项目程序是我自己的Demo程序&#xff0c;不会造成任何的财产侵害&#xff0c;本文仅作为日常记录及案例分享。实…

从0开始深度学习(35)——YOLO V5原理详解

以YOLO V5s为例&#xff0c;介绍YOLO V5的网络结构&#xff0c;以及其中具体的功能模块 1 YOLO V5的整体网络结构 YOLO V5网络结构分为四个部分&#xff1a; 输入端&#xff1a; 输入端负责对输入图像进行预处理&#xff0c;包括数据增强、锚框计算等。骨干网络&#xff08;Ba…

云计算vspere 安装过程

1 材料的准备 1 安装虚拟机 vmware workstation 2 安装esxi 主机 3 在esxi 主机上安装windows 2018 dns 服务器 4 在虚拟机上安装windows 2018 服务器 6 安装vcenter 5 登入界面测试 这里讲一下&#xff0c;由于部署vspere 需要在windows 2012 服务器上部…

微信小程序中使用miniprogram-sm-crypto实现SM4加密攻略

在微信小程序开发过程中&#xff0c;数据安全至关重要。本文将为大家介绍如何在微信小程序中使用miniprogram-sm-crypto插件进行SM4加密&#xff0c;确保数据传输的安全性。 一、SM4加密简介 SM4是一种对称加密算法&#xff0c;由国家密码管理局发布&#xff0c;适用于商密领…

算法-字符串-43.字符串相乘

一、题目 二、思路解析 1.思路&#xff1a; 1.双重for循环&#xff0c;倒序依次相乘 2.在倒序处理进位问题 3.最后返回参数的类型是string&#xff0c;用StringBuilder拼接&#xff0c;再转换为字符串 2.常用方法&#xff1a; 1.equals,比较对象内容是否一致 "0".eq…

vscode鼠标右键跳转到定义只能跳转到头文件

在使用Visual Studio Code进行C语言编程开发时&#xff0c;C/C插件出错&#xff0c;鼠标右键只能跳转到头文件&#xff0c;不能跳转到源代码中函数原型定义的地方。 解决办法 打开C/C拓展设置页面&#xff0c;点击卸载右边的小箭头&#xff0c;点击安装特定版本 安装老版本的C…

AI 数字人模型 Hallo2:让图片开口说话,一键修复模糊人脸

Hallo2 是由复旦大学 (Fudan University)、百度公司 (Baidu Inc) 和南京大学 (Nanjing University) 于 2024 年联合开发的一项先进技术&#xff0c;旨在生成长时间、高质量的唇形视频。该技术在原有的 Hallo 模型基础上进行了多项创新和改进&#xff0c;使其能够应对长时间视频…

模型训练数据-MinerU一款Pdf转Markdown软件

模型训练数据-MinerU一款Pdf转Markdown软件-说明 简介&#xff1a; MinerU是什么 MinerU是上海人工智能实验室OpenDataLab团队推出的开源智能数据提取工具&#xff0c;专注于复杂PDF文档的高效解析与提取。MinerU能将包含图片、公式、表格等元素的多模态PDF文档转化为易于分析…

Spring07——AOP通知以及几个相关案例

切入点表达式 注意&#xff0c;不是参数&#xff0c;是参数类型 可以使用通配符描述切入点&#xff0c;快速描述 ■ *&#xff1a;单个独立的任意符号&#xff0c;可以独立出现&#xff0c;也可以作为前缀或者后缀的通配符出现 execution(public∗com.itheima.∗.UserServi…

【ETCD】【源码阅读】configurePeerListeners() 函数解析

configurePeerListeners 是 ETCD 的一个核心函数&#xff0c;用于为集群中节点之间的通信配置监听器&#xff08;Peer Listener&#xff09;。这些监听器主要负责 Raft 协议的消息传递、日志复制等功能。函数返回一个包含所有监听器的列表。 函数签名 func configurePeerList…

Kafka怎么发送JAVA对象并在消费者端解析出JAVA对象--示例

1、在pom.xml中加入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-stream-kafka</artifactId><version>3.1.6</version></dependency> 2、配置application.yml 加入Kafk…

为了安全,自己搭建KMS,成功激活Office2010

在本篇文章中&#xff0c;将全过程描述Office Professional Plus 2010 With SP1 VOL从下载到自建KMS服务器再到激活的过程。本文展示的是64位版本&#xff0c;32位版本的方法类似。 特别注意&#xff1a;KMS激活仅限于VOL 版本&#xff0c;其他的零售版无法激活&#xff01;&am…