动静态库概念及创建
注意在库中不能写main()函数。
复习gcc指令 预处理-E
-> xx.i
编译 -S
-> xx.s
汇编 -c
-> xx.o
汇编得到的 xx.o
称为目标可重定向二进制文件,此时的文件需要把第三方库链接进来才变成可执行程序。
gcc -o mymath main.c myadd.c mysub.c
得到的mymath可以执行
gcc -o mymath main.o myadd.o mysub.o
得到的mymath可以执行
故可以不给别人源码.c文件,只给别人重定位目标二进制文件.o文件【方法实现】也是可以的,当然头文件【方法声明】也得给对方,才能通过编译。
思路:将*.o所有文件整体打包,给对方提供库文件!多个.o打包形成1个.o文件(库),其中打包的方式就决定了动静态库。
结论:1、库相当于*.o文件的集合;2、交付库==库文件.a/.so+头文件.h;
静态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
使用方法
生成静态库代码: ar -rc libxxx.a *.o
ar-archive-归档,Makefile文件内容
查看静态库中的目录列表ar -tv libxxx.a
libmymath.a:mysub.o myadd.oar -rc $@ $^
mysub.o:mysub.cgcc -c mysub.c -o mysub.o
myadd.o:myadd.cgcc -c myadd.c -o myadd.o.PHONY:output
output:mkdir -p mylib/includemkdir -p mylib/libcp -f *.a mylib/libcp -f *.h mylib/include.PHONY:clean
clean:rm *.o libmymath.a
接着打包tar czf mylib.tgz mylib
,正常流程就是把mylib.tgz放到yum资源,供人下载,别人下载然后解压tar xzf mylib.tgz
,接着安装cp mylib/include/*.h /user/include/
和cp mylib/lib/*.o /user/lib/
若要链接第三方库,必须要指明库的名称!以及指明库所在的路径!gcc编译指定路径 -I选项(头文件所在路径) -L选项(库文件所在路径) -l选项(库文件名称)gcc -o mymath main.c -I ./mylib/include -L ./mylib/lib -l mymath
注意库名称是去掉lib和.a/.so!
那为什么平时直接编译不用指明路径和库名称?因为gcc就只是编译C语言(只需要libc.a),g++就是编译C++的(只需要C++的库)。
接下来看代码如何制作静态库。
[yyq@VM-8-13-centos 2023_02_09_lib_dll]$ ll
total 12
-rw-rw-r-- 1 yyq yyq 213 Feb 9 15:01 main.c
drwxrwxr-x 4 yyq yyq 4096 Feb 9 13:47 mylib
[yyq@VM-8-13-centos 2023_02_09_lib_dll]$ gcc -o mymath main.c -I ./mylib/include -L ./mylib/lib -l mymath
[yyq@VM-8-13-centos 2023_02_09_lib_dll]$ ll
total 24
-rw-rw-r-- 1 yyq yyq 213 Feb 9 15:01 main.c
drwxrwxr-x 4 yyq yyq 4096 Feb 9 13:47 mylib
-rwxrwxr-x 1 yyq yyq 8480 Feb 9 15:03 mymath
[yyq@VM-8-13-centos 2023_02_09_lib_dll]$ ./mymath
Enter Add Func:> 10 + 20 = ?
result:>30
Enter Sub Func:> 10 - 20 = ?
result:>-10
[yyq@VM-8-13-centos 2023_02_09_lib_dll]$ ldd mymath//怎么都是动态链接的库呢??怎么看不到我们自己写的库名称?linux-vdso.so.1 => (0x00007fff23bb7000)libc.so.6 => /lib64/libc.so.6 (0x00007fca344ce000)/lib64/ld-linux-x86-64.so.2 (0x00007fca3489c000)
[yyq@VM-8-13-centos 2023_02_09_lib_dll]$ file mymath//为什么属性也是动态链接库呢??
mymath: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0f7725a095306499436d1394ed0d0ac1e5308b02, not stripped
//因为gcc默认是动态链接,对于特定的库取决于库本身是动态库还是静态库。要静态链接需要选项-static,动态库只能动态链接,静态库只能静态链接,动静都有默认动态。
//只要有1个动态库,那这个可执行程序就是动态链接的。
直接在命令行使用gcc太慢了,改进方法:1、把库放到系统路径/usr/include/
和/lib64/
。
原理
首先,静态库不需要加载到内存,是在链接阶段,将汇编生成的目标重定向二进制文件.o与引用到的库一起链接打包到可执行文件,即直接把那段需要的库代码拷贝到程序对应的代码段中【程序未被加载到内存的时候,就已经形成了虚拟地址(空间代码段、已初始化未初始化数据区、全局数据区),程序没有栈区和堆区】。当程序load到内存中,形成进程地址空间时,就有确定的地址位置(即进程地址空间的代码区只能访问程序的代码区)。
存在的问题
1、空间浪费。静态库在内存中存在多份拷贝导致空间浪费,
2、静态库对程序的更新、部署和发布页不友好。如果静态库libxx.lib更新了,所有使用它的应用程序都需要重新编译、发布给用户(对于用户来说,只是一个很小的改动,却导致整个程序重新下载,全量更新)。
动态库
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)。动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
使用方法
生成动态库的代码
gcc -fPIC -c mysub.c myadd.c
gcc -shared -o libmymath.so *.o
[yyq@VM-8-13-centos dynamicFile]$ ll
total 16
-rw-rw-r-- 1 yyq yyq 114 Feb 9 15:57 myadd.c
-rw-rw-r-- 1 yyq yyq 57 Feb 9 15:57 myadd.h
-rw-rw-r-- 1 yyq yyq 114 Feb 9 15:57 mysub.c
-rw-rw-r-- 1 yyq yyq 56 Feb 9 15:57 mysub.h
[yyq@VM-8-13-centos dynamicFile]$ gcc -fPIC -c myadd.c
[yyq@VM-8-13-centos dynamicFile]$ gcc -fPIC -c mysub.c
[yyq@VM-8-13-centos dynamicFile]$ ll
total 24
-rw-rw-r-- 1 yyq yyq 114 Feb 9 15:57 myadd.c
-rw-rw-r-- 1 yyq yyq 57 Feb 9 15:57 myadd.h
-rw-rw-r-- 1 yyq yyq 1592 Feb 9 15:59 myadd.o
-rw-rw-r-- 1 yyq yyq 114 Feb 9 15:57 mysub.c
-rw-rw-r-- 1 yyq yyq 56 Feb 9 15:57 mysub.h
-rw-rw-r-- 1 yyq yyq 1592 Feb 9 15:59 mysub.o
[yyq@VM-8-13-centos dynamicFile]$ gcc -shared -o libmymath.so *.o
[yyq@VM-8-13-centos dynamicFile]$ ll
total 32
-rwxrwxr-x 1 yyq yyq 8088 Feb 9 15:59 libmymath.so
-rw-rw-r-- 1 yyq yyq 114 Feb 9 15:57 myadd.c
-rw-rw-r-- 1 yyq yyq 57 Feb 9 15:57 myadd.h
-rw-rw-r-- 1 yyq yyq 1592 Feb 9 15:59 myadd.o
-rw-rw-r-- 1 yyq yyq 114 Feb 9 15:57 mysub.c
-rw-rw-r-- 1 yyq yyq 56 Feb 9 15:57 mysub.h
-rw-rw-r-- 1 yyq yyq 1592 Feb 9 15:59 mysub.o
[yyq@VM-8-13-centos dynamicFile]$ file libmymath.so
libmymath.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=bcfe08193c5605299db2b28596b7b96dedb08ab3, not stripped
[yyq@VM-8-13-centos dynamicFile]$ ldd libmymath.so linux-vdso.so.1 => (0x00007ffe02142000)libc.so.6 => /lib64/libc.so.6 (0x00007f66e790e000)/lib64/ld-linux-x86-64.so.2 (0x00007f66e7ede000)
[yyq@VM-8-13-centos mylib_dynamic]$ gcc -o mymath main.c -I./mylib/include -L./mylib/lib -lmymath//与静态库同样的编译代码再去编译形成可执行程序没问题,但是在执行时会报错,为什么呢?因为这里的指令都是告诉gcc需要的动态库在哪里以及叫什么名字,我们可以看一下这个可执行程序,它不知道我们自己写的动态库在哪里
[yyq@VM-8-13-centos mylib_dynamic]$ ldd mymath linux-vdso.so.1 => (0x00007ffd4e268000)libmymath.so => not foundlibc.so.6 => /lib64/libc.so.6 (0x00007fd9ac027000)/lib64/ld-linux-x86-64.so.2 (0x00007fd9ac3f5000)
//我们知道当gcc把程序编译完形成可执行程序后,后续的执行就与gcc无关了
//且动态库是程序运行后才链接的,程序运行起来就和OS相关了,但是OS不知道需要的动态库在哪叫什么,因此执行时会报错
解决方法1:直接把.so文件拷贝到可执行程序的同级路径下;
解决办法2:把我们写的库放到环境变量LD_LIBRARY_PATH去,但仅限本次登陆有效;
[yyq@VM-8-13-centos mylib_dynamic]$ echo $LD_LIBRARY_PATH
:/home/yyq/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
[yyq@VM-8-13-centos lib]$ pwd
/home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib
[yyq@VM-8-13-centos mylib_dynamic]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib
//这样可执行程序就能运行了,但是仅在本次登陆有效,下线后再次执行又不能跑了
解决办法3:cd /etc/ld.so.conf.d/
在这个路径下我们自己也写一个conf出来;
[yyq@VM-8-13-centos lib]$ ls /etc/ld.so.conf.d/
bind-export-x86_64.conf
dyninst-x86_64.conf
kernel-3.10.0-1160.71.1.el7.x86_64.conf
kernel-3.10.0-1160.76.1.el7.x86_64.conf
mysql-x86_64.conf
[yyq@VM-8-13-centos ld.so.conf.d]$ touch lib.conf
//在里面写出动态库的路径/home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib
[yyq@VM-8-13-centos ld.so.conf.d]$ cat lib.conf
/home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib
//接着更新一下conf,每次都能执行了
[yyq@VM-8-13-centos ld.so.conf.d]$ sudo ldconfig
解决办法4:采用软链接的方式。即在要运行可执行程序的路径下执行ln -s /home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib/libmymath.so libmymath.so
;
[yyq@VM-8-13-centos mylib_dynamic]$ ll
total 20
-rw-rw-r-- 1 yyq yyq 213 Feb 9 16:06 main.c
drwxrwxr-x 4 yyq yyq 4096 Feb 9 16:03 mylib
-rwxrwxr-x 1 yyq yyq 8432 Feb 9 16:17 mymath
[yyq@VM-8-13-centos mylib_dynamic]$ ln -s /home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib/libmymath.so libmymath.so
[yyq@VM-8-13-centos mylib_dynamic]$ ll
total 24
lrwxrwxrwx 1 yyq yyq 77 Feb 9 16:48 libmymath.so -> /home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib/libmymath.so
-rw-rw-r-- 1 yyq yyq 213 Feb 9 16:06 main.c
drwxrwxr-x 4 yyq yyq 4096 Feb 9 16:03 mylib
-rwxrwxr-x 1 yyq yyq 8432 Feb 9 16:17 mymath
还可以直接把这个软链接直接建到系统默认的库目录下
sudo ln -s /home/yyq/linux-class/2023_02_09_lib_dll/mylib_dynamic/mylib/lib/libmymath.so /lib64/libmymath.so
原理
以上我们所做的都是用gcc来完成编译,即把库路径、库名称、库文件告诉gcc,所以程序可以成功编译。那执行的时候呢?是要通过OS和shell来执行的,而这俩又不知道库路径这些数据,库也不在系统路径下,所以会出现最开始的链接失败的报错。给出的解决方案呢,是让OS和shell知道我们自己写的第三方动态库的名称、路径和文件,才能正确执行。
在执行时,OS将动态库中指定函数的偏移地址写入到我们的可执行程序中,OS提供页表将动态库代码映射到进程地址空间的共享区,此时库立马具备了在地址空间的起始地址,接着就能根据偏移量来找到指定函数(起始地址+偏移量=共享库中的地址->跳转访问)。【之前编译的时候使用该选项-fPIC与地址无关码,以该选项生成的动态库程序代码用的肯定是偏移地址(相对地址)】
- 动态链接有两种方式:装载时重定位和地址无关代码技术。
- 装载时重定位:在链接时对所有绝对地址的引用不作重定位,而把这一步推迟到装载时完成,也叫基址重置,每个指令和数据相当于模块装载地址是固定的,系统会分配足够大的空间给装载模块,当装载地址确定后,那指令和数据地址自然也就确定了。然而动态链接模块被装载映射到虚拟空间,指令被重定位后对于每个进程来讲是不同的,没有办法做到同一份指令被多个进程共享,所以指令对不同的进程来说有不同的副本,还是空间浪费,怎么解决这个问题?使用fPIC方法。
- 地址无关代码:指令部分无法在多个进程之间共享,不能节省内存,所以引入了地址无关代码的技术。我们平时编程过程中可能都见过-fPIC的编译选项,这个就代表使用了地址无关代码技术来实现真正的动态链接。基本思想就是使用GOT(全局偏移表),这是一个指向变量或函数地址的指针数组,当指令要访问变量或者调用函数时,会去GOT中找到相应的地址进行间接跳转访问,每个变量或函数都对应一个地址,链接器在装载模块的时候会查找每个变量和函数的地址,然后填充GOT中的各个项,确保每个指针指向的地址正确。GOT放在数据段,所以它可以在模块装载时被修改,并且每个进程都可以有独立的副本,相互不受影响。
优点
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦,用户只需要更新动态库即可,增量更新。
第三方库ncurses
ncurses库是用来处理屏幕显示情况的库,直接yum安装
相关文章:
动静态库概念及创建
注意在库中不能写main()函数。 复习gcc指令 预处理-E-> xx.i 编译 -S-> xx.s 汇编 -c-> xx.o 汇编得到的 xx.o称为目标可重定向二进制文件,此时的文件需要把第三方库链接进来才变成可执行程序。 gcc -o mymath main.c myadd.c mysub.c得到的mymath可以执…...

【H.264】码流解析 annexb vs avcc
H264码流解析及NALUAVCC和ANNEXB 前者是FLV容器、mp4 常用的。后者 是实时传输使用,所以是TS 一类的标准。VLC显示AVC1就是AVCC AVCC格式 也叫AVC1格式,MPEG-4格式,字节对齐,因此也叫Byte-Stream Format。用于mp4/flv/mkv, VideoToolbox。 – Annex-B格式 也叫MPEG-2 trans…...
【最优化方法】1-最优化方法介绍
文章目录1 最优化起源2 最优化发展3 运筹学在国外4 运筹学在国内5 什么是最优化?6 为什么要研究最优化问题?7 最优化问题8 最优化问题分类9 最优化研究内容理论算法应用1 最优化起源 中国古代优化思想–田忌赛马(公元前340年) 18世纪L.Euler࿰…...

数据结构 | 树 | 二叉树
🔥Go for it!🔥 📝个人主页:按键难防 📫 如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀 📖系列专栏:数据结构与算法 ὒ…...
笔记:使用 unbuild 搭建 JavaScript 构建系统笔记
使用 unbuild 搭建 JavaScript 构建系统jcLee95:https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 邮箱 :291148484163.com 简介: 本文是笔者阅读分析 elementPlus 项目时记录的。该项目用到了一个完全没有文档和资料的工具 unbu…...

【SpringBoot3.0源码】启动流程源码解析 •下
文章目录初始化DefaultBootstrapContext开启Headless模式获取监听器并启动封装命令行参数准备环境打印Banner创建上下文容器预初始化上下文容器刷新Spring容器打印启动时间发布事件执行特定的run方法上一篇《【SpringBoot3.0源码】启动流程源码解析 • 上》,主要讲解…...

QT(56)-动态链接库-windows-导出变量-导出类
1.导出变量 1.1不使用_declspec(dllimport) _declspec(dllexport) 使用_declspec(dllimport) _declspec(dllexport) 1.2win32 mydllwin32 myexe 1.3win32 mydllqt myexe 2.导出类 使用_declspec(dllimport) _declspec(dllexport) 2.1不用关键…...

TCP传输文件
传输文件和传输信息的区别: 传输信息,只是一条数据,传输文件是多条数据传输信息传输过去一般都会显示,传输文件一般不会显示,一般只是存放在文件中传输文件需要传输,文件大小和文件名称(不然不知…...

vue3:加载本地图片等静态资源
背景 在我们用 vue2 webpack 的时候,加载图片资源是这样用的: <img :src"require(/assets/test.png)" />这样打包后就会触发 file-loader 打包图片资源,在 dist 文件夹中就可以看到这个图片(如果图片较小会打包…...
工作记录------数据库group_concat函数长度问题
工作记录------group_concat函数长度问题 背景:页面在数据展示时,报错,错误显示:String index out of range: -1 异常信息 java.lang.StringIndexOutOfBoundsException: String index out of range: -1at java.lang.String.sub…...

Python基础语法
1 编程环境 1.1 编译环境 pycharmpython/anaconda 1.2 环境设置 File -> settings -> Project interpreter -> 1.3 Hello world 2 条件判断 2.1 例题 【题1】输入一个年份,判断是否是闰年 ①能被4整除,但不能被100整除; ②能被400整…...

windows环境下安装Nginx及常用操作命令
windows环境下安装Nginx及常用操作命令nginx基本概述基本用途nginx安装nginx基本概述 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器。基本用途 nginx是一个轻量级高并发服务器,而tomcat并不是。nginx一般被用来做反向代理,将请求转发到应用…...
python excel数据处理?
前段时间做了个小项目,帮个海洋系的教授做了个数据处理的软件。基本的功能很简单,就是对Excel里面的一些数据进行过滤,统计,对多个表的内容进行合并等。之前没有处理Excel数据的经验,甚至于自己都很少用到Excel。记得《…...

Hudi-集成Flink
文章目录集成Flink环境准备sql-client方式启动sql-client插入数据查询数据更新数据流式插入code 方式环境准备代码类型映射核心参数设置去重参数并发参数压缩参数文件大小Hadoop参数内存优化读取方式流读(Streaming Query)增量读取(Increment…...

重新认识 React Hooks useContext
通常来说,React 数据的传递方式都是一层一层把资料 props 传到子层的 就算第二层(Function Component)、第三层(Button Group Compontn) 根本没有用到这个资料,但是为了传到最底层(button) ,每一层还是必须要传props // App.js const App = () => {const [dark, setDark…...

数据库(2)--加深对统计查询的理解,熟练使用聚合函数
一、内容要求 利用sql建立学生信息数据库,并定义以下基本表: 学生(学号,年龄,性别,系号) 课程(课号,课名,学分,学时) 选课࿰…...

stm32f407探索者开发板(十五)——NVIC中断优先级管理
文章目录零、前言一、NVIC中断优先级分组1.1 中断的管理方法1.2 抢占优先级&相应优先级的区别1.3 举例1.4 特别说明1.5 中断优先级分组函数二、NVIC中断优先级设置2.1 中断设置相关寄存器2.2 中断设置优先级2.2.1 中断优先级控制的寄存器组 IP[240]2.2.2 中断使能寄存器组 …...

【Azure 架构师学习笔记】-Azure Logic Apps(6)- Logic Apps调用ADF
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Logic Apps】系列。 接上文【Azure 架构师学习笔记】-Azure Logic Apps(5)- 标准和使用量类型的区别 前言 Logic Apps 和 ADF 的搭配使用是常见的组合,它们可以互相弥补各自的不足和…...
python随机获取列表中某一元素
1、利用Python中的random模块中的choice方法 random.choice()可以从任何序列,比如list列表中,选取一个随机的元素返回,可以用于字符串、列表、元组等。 import random arr[1,2,3,4,5,6] print(random.choice(arr))2、利用Python中的random模…...

Nacos微服务笔记
Nacos安装Nacos 的 Github(Tags alibaba/nacos GitHub)下载我们所需的 Nacos 版本,可以选择 windows 或者 Linux。 进入官网,选择合适版本,tar.gz为linux版本,zip为windows版本。下载并解压 nacos-server…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...

Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...