cpp文件编译过程 makefile cmake

news2025/2/9 3:51:42

这里写目录标题

  • argc argv参数
  • 头文件
  • 编译过程
    • 静态链接,动态链接,静态库,动态库
  • -shared
    • 制作使用动态库
    • libxxx。so
    • 冲突
  • 静态库
  • 预处理
  • 编译
  • 汇编
  • 链接
  • 目录选项
    • -Idir 大写I
    • include<> 与 " "
    • -I -I- 与 -I- -I
  • ld/objdump/objcopy 选项
        • ld
        • objdump
        • objcopy
    • gcc -shared 和 ld
    • gcc -g
  • 多文件
    • 报错
  • 基于cmake
    • 调试
    • 注意
    • 注意2
  • cmake与mingw32-make.exe关系
  • task文件
    • 注意3
    • prelaunchtask
  • 多条指令 更改为 每次按F5调试一次性
  • settings.json 和cpp proporties.json
  • ctrl shift b
    • catkin make 和make

直接 gcc 没有-o 的话出来的输出exe文件没有调试信息,相比-o的大小会小一点,只有包含了调试信息文件才可以执行

argc argv参数

./hello shan
argc = 2
argv[0] = ./hello
argv[1] = shan

头文件

头文件在编译器的include目录中,编译时 -I 指定库
函数库默认路径在编译器的lib目录中,编译时 -L指定目录,-l 小写L 指定库
函数或者是在别的c与cpp文件中

find -name "stdio.h"

编译过程

在这里插入图片描述
在这里插入图片描述

gcc hello.c // 输出一个名为 a.out 的可执行程序,然后可以执行./a.out
gcc -o hello hello.c // 输出名为 hello 的可执行程序,然后可以执行./hello
gcc -o hello hello.c -static // 静态链接 默认情况使用动态链接
gcc -c -o hello.o hello.c // 先编译(不链接)
gcc -o hello hello.o // 再链接

执行“gcc -o hello hello.c -v”时,可以查看到这些步骤:
cc1 main.c -o /tmp/ccXCx1YG.s
as -o /tmp/ccZfdaDo.o /tmp/ccXCx1YG.s
cc1 sub.c -o /tmp/ccXCx1YG.s
as -o /tmp/ccn8Cjq6.o /tmp/ccXCx1YG.s
collect2 -o test /tmp/ccZfdaDo.o /tmp/ccn8Cjq6.o ....
可以手工执行以下命令体验一下:
gcc -E -o hello.i hello.c
gcc -S -o hello.s hello.i
gcc -c -o hello.o hello.s
gcc -o hello hello.o

静态链接,动态链接,静态库,动态库

静态链接(static linking)和动态链接(dynamic linking)都是将代码库连接到应用程序中的方法,以便于执行应用程序。

静态链接是将库中的所有代码复制到可执行文件中的过程。在编译时,编译器会将库的代码直接嵌入到最终生成的可执行文件中,因此可执行文件可以完全独立运行,无需依赖任何外部库或资源。这样做的好处是,可执行文件在不同机器或操作系统上的兼容性更高。缺点是,应用程序的大小通常会更大,并且更新库可能需要重新编译整个应用程序。

动态链接是将库的代码保留为单独的文件,操作系统只在应用程序运行时将其加载到内存中。因此,一个库的多个应用程序可以共享同一份库文件,从而节省了磁盘空间并减少了内存的使用。同时,如果有多个应用程序需要加载同一份库文件,那么这份文件只需要在内存中存在一次。这使得库的升级变得更加容易。然而,动态链接的应用程序依赖于系统中可用的动态库,如果要运行动态链接的应用程序,需要确保在系统上安装了所需的库。

静态库(static library)是一组预编译的目标文件或对象文件,它们被打包成一个文件并在编译时链接到应用程序中。静态库的代码完全复制到可执行文件中,因此它会增加可执行文件的大小。
优点是,静态库允许应用程序完全独立运行。缺点是,如果静态库的源代码发生变化,则必须重新编译整个应用程序。

动态库(dynamic library)是在运行时加载的库。动态库的代码只有一个副本,在内存中由多个应用程序共享。
动态库的优点是,多个应用程序可以使用同一份库文件,从而减少内存和磁盘空间。如果动态库的源代码发生变化,则只需要更新动态库文件本身即可。
缺点是,动态库在启动时需要额外的时间进行初始化,并且在不适当地使用时可能会导致内存泄漏或其他问题。

-shared

在 GCC 中,"-shared"选项用于指示编译器创建动态链接库(也称为共享库)而非可执行文件。

当使用"-shared"选项编译源文件时,GCC会将目标文件打包成一个控制导出符号的动态链接库。这意味着其他程序可以在运行时加载这个库,并链接到其中定义的符号和函数。共享库可以被多个应用程序共享,因此它们可以提高系统资源的利用率并减少内存占用量。

在您提供的命令中,使用"-shared"选项创建了一个名为"libsub.so"的动态链接库,其中包含 sub.o、sub2.o 和 sub3.o 编译后的目标文件。该库可以用于链接到其他程序中。

需要注意的是,如果库的依赖关系不正确,则可能会导致在加载库时发生错误。因此,在编译和链接动态库时,必须确保正确指定所有必需的库及其路径。

制作使用动态库

gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -shared -o libsub.so sub.o sub2.o sub3.o(可以使用多个.o 生成动态库)
gcc -o test main.o -lsub -L /libsub.so/所在目录/7步 运行:
① 先把 libsub.so 放到 Ubuntu 的/lib 目录,然后就可以运行 test 程序。
② 如果不想把 libsub.so 放到/lib,也可以放在某个目录比如/a,然后如下执
行:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a 
./test

这个命令将编译和链接 main.o 源文件,并将其与名为"libsub.so"的动态库链接起来。"-lsub"选项告诉编译器链接到名为"libsub.so"的库,"-L"选项则指定寻找库文件的路径。

因此,生成的可执行文件 test 将会依赖于名为"libsub.so"的动态链接库,而不是与其他默认库链接。

需要注意的是,如果要链接到多个库文件,则需要在命令行中指定所有这些库的名称(使用"-l"选项)和路径(使用"-L"选项)。否则,编译器将无法找到所需的库文件并产生错误。

libxxx。so

"-lsub"中的"sub"并不是随意命名的,而是根据动态库文件名"libsub.so"来确定的。

在默认情况下,GCC 会将库文件名解释为 libXXX.so 形式,其中 XXX 是库的名称。因此,在使用"-l"选项指定要链接的库时,可以省略"lib"和".so"部分,只指定库的名称即可。

例如,如果您有一个名为"libsub.so"的动态库,则可以使用"-lsub"选项将其链接到您的代码中。

需要注意的是,库文件名必须以"lib"开头,并以".so"结尾才能被识别为动态库。如果您的库文件名不符合这种命名约定,则需要使用"-l"选项显式指定完整的文件名和路径。

此外,您还可以使用"-Wl,-soname,NAME"选项来指定共享库的 soname,它是库的逻辑名称,是库的用户感知名称。例如,您可以使用以下命令来编译和链接一个共享库,并指定其 soname:

gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0.1 foo.o bar.o

这将生成一个名为"libfoo.so.1.0.1"的共享库,并将其逻辑名称设置为"libfoo.so.1"。这样,用户可以链接到"libfoo.so.1"而不必担心底层库的实际名称和版本。

冲突

在这个例子中,使用-Wl,-soname,libfoo.so.1选项指定了库的逻辑名称为"libfoo.so.1",而不是默认的"libfoo.so"。并且使用-o libfoo.so.1.0.1选项指定生成的共享库名称为"libfoo.so.1.0.1"。这样设计的目的是为了在为共享库命名时提供更多的灵活性和精确度。

foo.o bar.o是需要链接进共享库的目标文件列表。

如果要将这个共享库链接到其他程序中,则需要使用-lfoo选项将其指定为依赖库。

例如,如果你想编译一个名为test的程序,并链接上面的共享库,则可以使用以下命令:

gcc -o test test.o -L/path/to/lib -lfoo

其中,-L选项用于指定共享库所在的路径,-lfoo选项用于指定需要链接的库的名称。编译器将搜索指定路径下的libfoo.solibfoo.a文件,并将其链接到程序中。由于我们已经在编译共享库时使用了-Wl,-soname,libfoo.so.1选项来指定了逻辑名称,因此链接器将自动匹配库的名称为"libfoo.so.1",而不是"libfoo.so"。

需要注意的是,如果在链接时指定的共享库名称不是由-Wl,-soname选项指定的逻辑名称,则可能会导致运行时错误。此外,如果要链接的库不在默认路径中,还需要使用-rpath选项来指定运行时搜索库的路径,以确保程序能够正确地加载库。

如果目录下同时有libfoo.so.1.0.1libfoo.so这两个文件,那么在使用-lfoo选项编译链接程序时,链接器可能会优先选择libfoo.so而不是libfoo.so.1.0.1,因为它具有更短的名称。

为了避免这种情况的发生,我们一般会将动态库的版本号包含在库文件名中,以便在有多个版本的库文件存在时,可以根据需要精确地选择需要的版本。例如,在之前的例子中,-soname选项指定了逻辑名称为"libfoo.so.1",因此生成的共享库的实际名称为libfoo.so.1.0.1,这样可以避免与libfoo.so发生命名冲突。

另外,你也可以通过设置LD_LIBRARY_PATH环境变量来改变动态库的搜索路径,这样可以让链接器在默认路径之外搜索动态库。例如:

export LD_LIBRARY_PATH=/path/to/libs:$LD_LIBRARY_PATH

这将把/path/to/libs目录添加到动态库的搜索路径中。然后,当你使用-lfoo选项编译链接程序时,链接器会先在/path/to/libs目录下查找libfoo.solibfoo.so.1.0.1文件,如果找到则使用它。

是的,通常情况下,我们会将不同版本的.so文件放到不同的目录中,这样可以避免不同版本之间的文件名冲突问题。

在编译时,你可以通过-L选项来添加库文件的搜索路径。例如:

gcc -o myprogram myprogram.o -L/path/to/libs -lfoo

这里的-L/path/to/libs选项指定了库文件所在的路径为"/path/to/libs",而-lfoo选项指定了需要链接的库的名称为"libfoo.so"或"libfoo.a"。如果这个路径中有多个不同版本的库文件,链接器会根据库文件的版本号以及程序对特定版本的库的需求来自动选择合适的库文件进行链接。

当程序运行时,动态链接器将会按照一定的规则搜索库文件,并将其加载到内存中供程序使用。具体的搜索顺序可以通过设置LD_LIBRARY_PATH或修改/etc/ld.so.conf等方式来改变,这样可以使动态链接器在不同的目录中查找库文件。

静态库

在编译好上面提到的两个目标文件(main.o和sub.o)后,你可以使用ar命令来将它们打包成静态库。具体来说,你需要执行以下命令:

ar rcs libmystatic.a main.o sub.o

其中,r选项表示将目标文件添加到静态库中(如果目标文件已经存在于静态库中,则将其替换),c选项表示创建一个新的静态库,如果静态库不存在则创建,s选项表示为静态库创建索引表,以提高链接速度。libmystatic.a是指定生成的静态库文件名。

执行完以上命令后,就会在当前目录下生成名为libmystatic.a的静态库文件。你可以使用nm命令来查看静态库中包含的符号列表,例如:

nm libmystatic.a

如果要使用这个静态库来链接其它程序,可以使用-L-l选项,例如:

gcc -o myprogram myprogram.o -L. -lmystatic

这里的-L.选项表示在当前目录中搜索库文件,而-lmystatic选项表示链接名为libmystatic.a的静态库。在链接阶段,静态库被直接嵌入到可执行程序中,因此在运行时不需要依赖外部库文件。

预处理

以#开头的就是预处理命令

编译

生成汇编代码,使用到了ccl工具

汇编

生成机器代码,用到的工具为as

链接

将上步生成的OBJ文件和系统库的OBJ文件,库文件链接起来
用到的工具为ld或collect2

目录选项

-Idir 大写I

比如 -I. 表示在当前目录下搜索
-Idir选项是用来指定编译器在搜索头文件时需要添加的目录路径。具体来说,当你在代码中使用#include <header.h>形式的语句时,编译器会在一些默认的目录和用户指定的目录中查找header.h头文件,如果找到则进行编译,否则就报错。

这里的-I选项就是用来指定额外的头文件搜索路径的。例如,假设你的头文件位于/usr/local/include目录下,那么你可以通过以下命令来指定这个目录为头文件搜索路径:

gcc -o myprogram myprogram.c -I/usr/local/include

这样,编译器在搜索头文件时就会先搜索/usr/local/include目录,如果目录下存在需要的头文件,则不会报错。

需要注意的是,-I选项仅仅是将指定的目录添加到搜索路径中,并不会取代默认的搜索路径。如果你希望完全使用自定义的头文件搜索路径,可以使用-nostdinc选项禁止编译器使用默认的搜索路径。例如:

gcc -o myprogram myprogram.c -nostdinc -I/usr/local/include

这样,编译器就只会按照-I选项中指定的路径搜索头文件了。

include<> 与 " "

如果以“#include < >”包含文件,则只在标准库
目录开始搜索(包括使用-Idir 选项定义的目录);如果以“#include “ ””包
含文件,则先从用户的工作目录开始搜索,再搜索标准库目录。

-I -I- 与 -I- -I

-I -I-  只 适 用 于 `#include 
"file"'这种情况;它们不能用来搜索`#include <file>'包含的头文件


-I-  -I
可以在这些路径中搜索
所有的`#include'指令(一般说来-I 选项就是这么用的)

ld/objdump/objcopy 选项

ldobjdumpobjcopy都是常用的GNU工具,它们在各自的领域内都有很多实用的选项。

ld

ld是用来将多个目标文件链接成一个可执行文件或动态链接库的工具。它的一些常用选项如下:

  • -o file:指定输出文件名称;
  • -l library:指定需要链接的库;
  • -L path:指定库搜索路径;
  • -shared:生成动态链接库;
  • -static:静态链接所有库。

objdump

objdump是一个反汇编器,可以将目标文件反汇编为汇编代码。它的一些常用选项如下:

  • -D:反汇编所有节(包括已被标记为debugging信息的节);
  • -S:反汇编同时显示源代码;
  • -M options:设置反汇编器选项,例如-Mintel表示使用Intel语法。

objcopy

objcopy是一个目标文件格式转换工具,可以将目标文件从一种格式转换为另一种格式,也可以改变目标文件的各种属性等。它的一些常用选项如下:

  • -O format:指定转换后的目标文件格式;
  • --strip-all:删除所有符号表及重定位表等调试信息;
  • --strip-debug:删除debugging信息;
  • --only-section name:只拷贝指定的节。

这些工具在开发和调试过程中非常有用,可以帮助开发者完成目标文件的相关操作,例如链接库、调试和格式转换等。

gcc -shared 和 ld

ldgcc -shared都可以用来生成动态链接库,它们在功能上确实是相当的。不过,gcc -shared命令其实是一个包含了gccld的封装工具,它可以将多个目标文件和库文件链接成一个动态链接库,而且更加简单易用。

具体来说,gcc -shared的使用方式如下:

gcc -shared -o libmymodule.so mymodule.o

这条命令会将mymodule.o目标文件链接为名为libmymodule.so的动态链接库。其中,-shared选项表示生成动态链接库,-o选项用于指定输出文件的名称和路径。

与之相比,直接使用ld生成动态链接库需要手动指定很多参数,例如链接器脚本、链接器选项等,相对比较麻烦。因此,在实际开发中,通常优先考虑使用gcc -shared命令生成动态链接库。

gcc -g

gcc -g是用来生成调试信息的编译选项之一。指定了-g选项,就可以在编译生成的目标文件中嵌入调试信息,方便程序调试。

具体来说,使用gcc -g命令编译源代码时,会在生成的可执行文件中嵌入调试符号表,包含了函数名、变量名等信息,同时还包含了源代码的行号和文件名等信息。这些调试信息可以帮助开发者定位和修复程序的bug。

例如,假设有一个名为test.c的C语言源文件,可以通过以下命令来生成带调试信息的可执行文件:

gcc -g -o test test.c

其中,-o选项用于指定输出文件名称,-g选项用于生成调试信息。

需要注意的是,在生产环境中,通常不建议在生产代码中包含调试信息,因为它会增加可执行文件的体积,并且可能泄漏敏感信息。因此,需要在生成生产环境可执行文件时去掉-g选项。

多文件

xxx.h里面声明
xxx.cpp include "xxx.h"函数实现

main.cpp include "xxx.h"

gcc -g .\main.cpp .\xxx.cpp -o my_multi


报错

自动生成的task是编译单个文件的
需要自己配置launch和task文件

他视频里是通过自己的 gcc命令生成命令了
就只需要改动launch文件下的
program值 指定生成的exe文件路径
然后把 prelaunchtask给注释。

基于cmake

创建 cmakelist.txt


project(myswap)

add_executable(文件名字别称 文件名.cpp  文件2.cpp)  

ctrl shift p
选定cmake编译器
Cmake:configure
然后选择
GCC 8.1.0 编译器

在这里插入图片描述
可以看到终端信息以及生成的build文件夹
之后回到终端中

再build目录下执行

cmake..

他会到上一级目录查找CMakeLists.txt文件并生成相应的构建工程。最后,再执行make命令,将源代码编译成可执行文件或库文件等二进制文件,并将其输出到build目录下。

因此,在使用CMake进行非ROS项目构建时,你必须确保使用正确的目录结构,即将源代码存放在根目录下,而将构建过程中生成的中间文件和构建工件等内容存放在build目录下。如果你需要直接修改或查看具体的编译文件,可以到build目录下找到,但一般来说在大多数情况下,你只需要在build目录下找到最终的可执行文件或库文件等内容即可。

在这里插入图片描述
之后linux和windows下执行的程序不太一样,这里执行了 mingw32-make.exe
可以看到编译, 然后是链接,生成文件
在这里插入图片描述

调试

要到launch.json下给到program路径,同样把prelaunch给注释掉
在这里插入图片描述

注意

在这里插入图片描述

注意2

当cpp代码更改后,如果把prelaunch代码注释了,调试的时候他不会生成新的可执行文件,他是按照旧的代码运行的。
当重新执行 mingw32命令后,他重新building,linking,buildt后才会执行新的代码。

cmake与mingw32-make.exe关系

CMake是一款跨平台的自动化建构系统,可以帮助开发者在不同的操作系统和编译环境下生成可执行文件、库文件等项目产物。执行CMake命令会根据CMakeLists.txt中的描述生成相应的Makefile或Visual Studio工程等项目文件,然后使用Make或Visual Studio等原生工具对项目进行编译和链接。

当你使用CMake生成了Makefile之后,你还需要执行make命令或mingw32-make.exe命令(如果你正在使用MinGW32编译器的话)来实际编译和链接项目代码,最终生成可执行文件或库文件等项目产物。

具体来说,在执行mingw32-make.exe命令时,它会读取Makefile文件中的指令和依赖关系,按照规定的顺序对源代码进行编译和链接。通过这种方式,编译器会将源代码编译成目标文件,链接器则将目标文件与库文件等依赖项进行链接,最终生成可执行文件或库文件等项目产物。

总之,CMake负责生成Makefile文件,而mingw32-make.exe负责根据Makefile文件中的指令和依赖关系对项目进行编译和链接。因此,在使用CMake生成Makefile之后,你需要通过运行mingw32-make.exe来完成整个项目的编译和链接过程。

task文件

当你把launch文件里的prelaunchtask注释取消后,F5按下后报错

系统里没有执行 名称为xxx的task,你需要创建这个task,
ctrl shift p ------ task configuration
或者 c/c++ g++.exe build active file creat task from file

在这里插入图片描述

相当于就是在shell中执行了 command,
g++ -g  (文件名)main.cpp swap.cpp -o out.exe
默认生成的是单文件调试,此时需要将${file} 改为 "main.cpp","swap.cpp",
同时需要将最后一个参数改为输出文件所需要的文件名参数

注意3

他这里重现编译了,需要再次更改 program的文件路径
在这里插入图片描述

在这里插入图片描述
生成路径和指向路径要对应

prelaunchtask

最为关键的作用, 就是调试的时候会先调用 prelaunch的task任务,进行编译生成。否则就会默认调用之前生成的文件。
相当于调用task文件里的指令

多条指令 更改为 每次按F5调试一次性

每次更改代码都要执行多条指令,比如说make以及mingw32等等。
可以全部整合到task.josn文件中

到达build目录空间下
在这里插入图片描述

在这里插入图片描述
三个lable三个task,第三个lable包含了前两个task
这里需要把第二个task的command的 make 改为 mingw32-make.exe
需要到launch中prelaunchtask名字改为 Build

settings.json 和cpp proporties.json

ros课堂里面的 什么自定义srv文件 msg文件都是在这里面配置的

ctrl shift b

{
// 有关 tasks.json 格式的文档,请参见
    // https://go.microsoft.com/fwlink/?LinkId=733558
    "version": "2.0.0",
    "tasks": [
        {
            "label": "catkin_make:debug", //代表提示的描述性信息
            "type": "shell",  //可以选择shell或者process,如果是shell代码是在shell里面运行一个命令,如果是process代表作为一个进程来运行
            "command": "catkin_make",//这个是我们需要运行的命令
            "args": [],//如果需要在命令后面加一些后缀,可以写在这里,比如-DCATKIN_WHITELIST_PACKAGES=“pac1;pac2”
            "group": {"kind":"build","isDefault":true},
            "presentation": {
                "reveal": "always"//可选always或者silence,代表是否输出信息
            },
            "problemMatcher": "$msCompile"
        }
    ]
}




这段文本是一个 `tasks.json` 文件的示例,用于定义 Visual Studio Code 编辑器中工作区的任务列表。该示例包含一个名为 `catkin_make:debug` 的任务,用于在 ROS (Robot Operating System) 环境下编译项目代码并生成调试版本的二进制文件。

具体来说,`tasks` 数组中的每个元素都表示一个任务,该示例中只定义了一个任务。下面对各个字段进行解释:

1. `"label"`:任务的标签,用于在编辑器中显示该任务的描述信息;
2. `"type"`:任务类型,可以是 "shell" 或者 "process"。如果是 "shell",则表示该任务使用 shell 命令,在终端中运行,如果是 "process",则表示该任务以进程的方式运行;
3. `"command"`:表示需要执行的命令,该示例中需要执行的命令是 `catkin_make`;
4. `"args"`:表示执行命令时传递的参数,该示例中没有传递任何参数;
5. `"group"`:表示任务所属的分组,可以指定 build、test、或者其他自定义分组。该示例中将该任务设置为默认构建任务;
6. `"presentation"`: 表示任务执行过程中输出信息的提示配置。在该示例中设置为 `reveal: "always"`,表示总是在终端中显示任务的输出信息;
7. `"problemMatcher"`: 表示用于匹配输出信息中的错误信息的正则表达式,以便错误信息可以在编辑器中被定位和高亮显示。该示例中使用了 Visual C++ 的问题匹配器,用于匹配 C/C++ 编译器输出的错误信息。

总之,这段示例代码定义了一个 "catkin_make:debug" 的任务,用于在 ROS 环境下编译项目代码,并生成调试版本的二进制文件。该任务被设置为默认构建任务,并在终端中输出任务的输出信息。


在 Microsoft Visual Studio Code 编辑器中,使用快捷键 Ctrl + Shift + B 可以调用编译命令,可以快速编译并构建项目。

但需要注意的是,这个组合键需要先配置对应的编译任务才能正常工作。具体来说,你需要在 Visual Studio Code 中打开项目文件夹,然后使用菜单栏中的“终端”菜单或快捷键 Ctrl + ~ 打开集成终端。接着,在终端中输入 task list 命令,查看当前项目中已经定义的所有任务。

如果没有定义编译任务,可以通过添加 tasks.json 文件来定义编译任务,例如:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "g++",
            "args": [
                "-o",
                "hello",
                "hello.cpp"
            ]
        }
    ]
}

这个示例中,我们定义了一个名为 build 的编译任务,它的命令是 g++ -o hello hello.cpp。执行 Ctrl + Shift + B 快捷键时,Visual Studio Code 会自动查找并执行名为 build 的任务,从而完成编译操作。

总之,使用快捷键 Ctrl + Shift + B 调用编译命令需要先配置相应的编译任务,并确保该任务的名称与 tasks.json 文件中定义的一致。

catkin make 和make

分别为cmake 和 make -j8 -l8
跑完第一条后在相应目录跑第二条, 他这里是在linux下 所以后面一条命令是make,这样的话就说的通了

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

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

相关文章

内网渗透—隧道搭建Ngrok与Frp内网穿透

这里写目录标题 1. 前言1.1. 隧道技术介绍1.2. 代理技术介绍1.2.1. 正向代理1.2.2. 反向代理1.2.3. 透明代理1.2.4. 正向代理与透明代理区别 2. 内网穿透2.1. Ngrok2.1.1. 访问Ngrok2.1.2. 代理设置2.1.2.1. 开通代理2.1.2.2. 配置隧道2.1.2.3. 下载客户端 2.1.3. 配置客户端2.…

P20[6-8]编码器接口测速(软)

与外部中断编码器逻辑不同,此处编码器使用的是定时器方法 1.Encoder编码器部分: #include "stm32f10x.h" // Device header void Encoder_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCm…

吐血整理,自动化测试场景处理(多场景覆盖)+解决方案

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、添加时间等待 …

53.最大子数组和

贪心算法 时间复杂度&#xff1a;代码中只有一个循环&#xff0c;循环次数为数组的长度&#xff0c;因此时间复杂度为 O(n)&#xff0c;其中 n 是数组的长度。空间复杂度&#xff1a;代码中只使用了常数级别的额外空间&#xff0c;因此空间复杂度为 O(1)。 这段代码使用贪心算…

QT C++入门学习(2) QT Creator写一个简单的上位机控制LED

上位机和下位机的概念 上位机&#xff1a;指的是可以直接发送操作指令的计算机或者单片机&#xff0c;一般提供用户操作交互界面并向用户展示反馈数据。 典型设备&#xff1a;电脑、平板、手机、面板、触摸屏 下位机&#xff1a;指的是与机器相连接的计算机或者单片机&#…

Studio 3T 2023.5 (macOS, Linux, Windows) - MongoDB 的专业 GUI、IDE 和 客户端

Studio 3T 2023.5 (macOS, Linux, Windows) - MongoDB 的专业 GUI、IDE 和 客户端 请访问原文链接&#xff1a;https://sysin.org/blog/studio-3t-2023/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Studio 3T&#xff0c;M…

黑客松必备|Bear Necessities Hackathon Office Hours汇总

由Moonbeam和AWS Startups联合主办的Bear Necessities Hackathon黑客松启动仪式已于5月30日举行。本次黑客松将历时约1个月的时间&#xff0c;包含6个挑战&#xff0c;分别由Moonbeam基金会、Chainlink、StellaSwap、SubQuery、Biconomy提供赞助&#xff0c;总奖池超过5万美金。…

面试软件测试时,面试官最想听到的答案是什么?

问题&#xff1a;面试软件测试时&#xff0c;面试官让你测一个软件&#xff0c;比如朋友圈&#xff0c;或者让你测试你的电脑为什么打不开网页&#xff0c;而QQ可以打开之类的&#xff0c;他最想听到的答案是什么&#xff1f; 如上所述&#xff0c;在实际面试中&#xff0c;面试…

懂点测试基础就敢要17k? 面试官:最多8K,多一分都没有...

公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-25k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。看简历很多都是3年工作经验&#xff0c;但面试…

Java泛型的使用

1.什么是泛型&#xff1f; 所谓泛型&#xff0c;就是允许在定义类、接口时通过 一个标识 表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时&#xff08;例如&#xff0c;继承或实现这个接口&#xff0c;用这个类型声明变量、创建对象时&#…

5.Opencv-图像滤波(均值,方框,高斯,中值,双边滤波)

常见的图像滤波操作有&#xff1a; 均值滤波&#xff08;cv2.blur&#xff09; 方框滤波&#xff08;cv2.boxFilter&#xff09; 高斯滤波&#xff08;cv2.GaussianBlur&#xff09; 中值滤波&#xff08;cv2.medianBlur&#xff09; 双边滤波&#xff08;cv2.bilateralFilter…

电脑小白不要错过这五款小众但强大的软件

电脑上的各类软件有很多&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;专注于实用功能&#xff0c;简洁干净、功能强悍。 多语言翻译——QTranslate QTranslate是一款实用的多语言翻译工具。它可以在任何应用程序中选中文本&#…

【C++】模版进阶

目录 一、非类型模版参数二、模板的特化1、概念2、函数模版特化3、类模板特化1.全特化2.偏特化3.类模板特化应用示例 三、模版分离编译1、什么是分离编译2、模板的分离编译3、模板的优缺点 一、非类型模版参数 模版参数分为类型模版参数与非类型模版参数 类型模版参数&#x…

一定要看!带你选择适合自己的测试工具

目录 前言&#xff1a; Jmeter实现接口请求JSON断言 Postman接口请求断言 前言&#xff1a; 选择适合的测试工具对于测试人员和测试项目的成功非常重要。不同的测试工具都有其独特的优缺点&#xff0c;而且每个项目的需求也不尽相同。因此&#xff0c;在选择测试工具时&#…

使用vitepress快速搭建个人网站或官方文档网站

使用vitepress快速搭建个人网站或官方文档网站 1. vitepress是什么&#xff1f; 官方首页的介绍&#xff0c; 翻译过来就是&#xff0c;vite和vue组成的强大的静态网站构造器。简单、强大和快速&#xff0c;是你一直想要的SSG(Static Site Generator)框架。 官网地址&#…

python mitmproxy抓包库

一.简介 mitmproxy是一款用Python编写的支持HTTP(S)的中间人代理工具。它可以拦截、查看、修改、重放和保存HTTP/HTTPS流量 &#xff0c;支持命令行界面和图形界面&#xff0c;可用于安全测试、网络调试、API开发和反向工程等场景。mitmproxy具有很高的灵活性和扩展性&#xf…

GUT|IF30+的联合分析文章:宏基因加代谢组

● 代谢组学是基于LC-MS/MS液质联用技术对生物样本中的小分子代谢物进行定性和相对定量分析&#xff1b; ● 宏基因组-代谢组的联合分析可以用来解释差异菌群与差异代谢物的关联性&#xff1b; ● 从而帮助建立微生物-代谢物-表型之间的逻辑关系。 凌恩生物的宏基因组学引入了…

JS:yFiles for HTML Complete 2.5.0 Crack

yFiles for HTML Complete 是市场上最先进、最完整的图表解决方案。我们强大而灵活的 API 提供了广泛的功能——开箱即用。只需选择最符合您需求的那些。 适用于每个用例的布局 从大量预定义的布局中进行选择并配置它们以完美地适应手头的任务。 yFiles 提供业内最广泛的高质量…

Sentinel与Hystix的线程隔离有什么差别

线程隔离有两种方式实现&#xff1a; 线程池隔离&#xff08;hystix 默认采用&#xff09; 优点&#xff1a;支持主动超时&#xff0c;支持异步调用 缺点&#xff1a; 线程的额外开销比较大 场景&#xff1a; 低扇出&#xff08;服务A调用服务B这种简单的调用&#xff09;信号…

新能源共享叉车充电桩管理系统设计思路

一、充电桩系统设计思路 1、总后台端&#xff0c;电脑版 1.1运营商管理。后台可以添加运营商&#xff0c;运营商可以添加无限添加充电站、充电桩、站点合伙人、充电操作员等&#xff0c;运营商、站点合伙人均有独立的后台入口&#xff0c;可以管理和查看与当前运营商相关充电站…