<delect id="571mh"></delect>

  • <track id="571mh"></track>
        1. 侵权投诉

          四个方面全面解析Linux 下 C++ 编译&amp;链接

          开关电源芯片 ? 2021-08-27 09:36 ? 次阅读

          【导读】:编译与链接对C++&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译与链接过程,陌生在于大部分人并不会刻意关注编译与链接的原理。本文通过开发过程中碰到的四个典型问题来探索64位linux下C++编译&链接的那些事。

          以下是正文

          编译原理

          将如下最简单的C++程序(main.cpp)编译成可执行目标程序,实际上可以分为四个步骤:预处理、编译、汇编、链接,可以通过

          g++ main.cpp –v看到详细的过程,不过现在编译器已经把预处理和编译过程合并。

          预处理:g++ -E main.cpp -o main.ii,-E表示只进行预处理。预处理主要是处理各种宏展开;添加行号和文件标识符,为编译器产生调试信息提供便利;删除注释;保留编译器用到的编译器指令等。

          编译:g++ -S main.ii –o main.s,-S表示只编译。编译是在预处理文件基础上经过一系列词法分析、语法分析及优化后生成汇编代码。

          汇编:g++ -c main.s –o main.o?;惚嗍墙惚啻胱骺梢灾葱械闹噶?。

          链接:g++ main.o。链接生成可执行程序,之所以需要链接是因为我们代码不可能像main.cpp这么简单,现代软件动则成百上千万行,如果写在一个main.cpp既不利于分工合作,也无法维护,因此通常是由一堆cpp文件组成,编译器分别编译每个cpp,这些cpp里会引用别的??橹械暮蛉直淞?,在编译单个cpp的时候是没法知道它们的准确地址,因此在编译结束后,需要链接器将各种还没有准确地址的符号(函数、变量等)设置为正确的值,这样组装在一起就可以形成一个完整的可执行程序。

          问题一:头文件遮挡

          在编译过程中最诡异的问题莫过于头文件遮挡,如下代码中main.cpp包含头文件common.h,真正想用的头文件是图中最右边那个包含name

          c984c19a-f62b-11eb-9bcf-12bb97331649.png

          成员的文件(所在目录为。/include),但在编译过程中中间的common.h(所在目录为。/include1)抢先被发现,导致编译器报错:Test结构没有name成员,对程序员来讲,自己明明定义了name成员,居然说没有name这个成员,如果第一次碰到这种情况可能会怀疑人生。应对这种诡异的问题,我们可以用-E参数看下编译器预处理后的输出,如下图。

          c9b0d500-f62b-11eb-9bcf-12bb97331649.jpg

          预处理文件格式如下:# linenum filename flag,表示之后的内容是从文件名为filaname的文件中第linenum行展开的,flag的取值可以是1,2,3,4,可以是用空格分开的多值,1表示接下来要展开一个新文件;2表示一个文件展开完毕;3表示接下来内容来自一个系统头文件;4表示接下来的内容应该看做是extern C形式引入的。

          从展开后的输出我们可以清楚地看到Test结构确实没有定义name这个成员,并且Test这个结构是在。/include1中的common.h中定义的,到此真相大白,编译器压根就没用我们定义的Test结构,而是被别的同名头文件截胡了。我们可以通过调整-I或者在头文件中带上部分路径更详细制定头文件位置来解决。

          目标文件:

          编译链接最终会生成各种目标文件,Linux下目标文件格式为ELF(Executable Linkable Format),详细定义见/usr/include/elf.h头文件,常见的目标文件有:可重定位目标文件,也即.o结尾的目标文件,当然静态库也归为此类;可执行文件,比如默认编译出的a.out文件;共享目标文件.so;核心转储文件,也就是core dump后产出的文件。Linux文件格式可以通过file命令查看。

          一个典型的ELF文件格式如下图所示,文件有两种视角:编译视角,以section头部表为核心组织程序;运行视角,程序头部表以segment为核心组织程序。这么做主要是为了节约存储,很多细碎的section在运行时由于对齐要求会导致很大的内存浪费,运行时通?;峤ㄏ蘩嗨频膕ection组织成segment一起加载。

          通过命令objdump和readelf可以查看ELF文件的内容。

          对可重定位目标文件常见的section有:

          ca2e1600-f62b-11eb-9bcf-12bb97331649.png

          符号解析:

          链接器会为对外部符号的引用修改为正确的被引用符号的地址,当无法为引用的外部符号找到对应的定义时,链接器会报undefined reference to XXXX的错误。另外一种情况是,找到了多个符号的定义,这种情况链接器有一套规则。在描述规则前需要了解强符号和弱符号的概念,简单讲函数和已初始化的全局变量是强符号,未初始化的全局变量是弱符号。

          针对符号的多重定义链接器处理规则如下(作者在gcc 7.3.0上貌似规则2,3都按1处理):

          1. 不允许多个强符号定义,链接器会报告重复定义貌似的错误

          2. 如果一个强符号和多个弱符号同名,则选择强符号

          3. 如果符号在所有目标文件中都为弱符号,那么选择占用空间最大的一个

          有了这些基础,我们先来看一下静态链接过程:

          1. 链接器从左到右按照命令行出现顺序扫描目标文件和静态库

          2. 链接器维护一个目标文件的集合E,一个未解析符号集合U,以及E中已定义的符号集合D,初始状态E、U、D都为空

          3. 对命令行上每个文件f,链接器会判断f是否是一个目标文件还是静态库,如果是目标文件,则f加入到E,f中未定义的符号加入到U中,已定义符号加入到D中,继续下一文件

          4. 如果是静态库,链接器尝试到静态库目标文件中匹配U中未定义的符号,如果m中匹配U中的一个符号,那么m就和上步中文件f一样处理,对每个成员文件都依次处理,直到U、D无变化,不包含在E中的成员文件简单丢弃

          5. 所有输入文件处理完后,如果U中还有符号,则出错,否则链接正常,输出可执行文件

          问题二:静态库顺序

          如下图所示,main.cpp依赖liba.a,liba.a又依赖libb.a,根据静态链接算法,如果用g++ main.cpp liba.a libb.a的顺序能正常链接,因为解析liba.a时未定义符号FunB会加入到上述算法的U中,然后在libb.a中找到定义。

          如果用g++ main.cpp libb.a liba.a的顺序编译,则无法找到FunB的定义,因为根据静态链接算法,在解析libb.a的时候U为空,所以不需要做任何解析,简单抛弃libb.a,但在解析liba.a的时候又发现FunB没有定义,导致U最终不为空,链接错误。

          因此在做静态链接时,需要特别注意库的顺序安排,引用别的库的静态库需要放在前面,碰到链接很多库的时候,可能需要做一些库的调整,从而使依赖关系更清晰。

          ca48b7c6-f62b-11eb-9bcf-12bb97331649.png

          动态链接:

          之前大部分内容都是静态链接相关,但静态链接有很多不足:不利于更新,只要有一个库有变动,都需要重新编译;不利于共享,每个可执行程序都单独保留一份,对内存和磁盘是极大的浪费。

          要生成动态链接库需要用到参数“-shared -fPIC”表示要生成位置无关PIC(Position Independent Code)的共享目标文件。对静态链接,在生成可执行目标文件时整个链接过程就完成了,但要想实现动态链接的效果,就需要把程序按照??椴鸱殖上喽远懒⒌牟糠?。

          在程序运行时将他们链接成一个完整的程序,同时为了实现代码在不同程序间共享要保证代码是和位置无关的(因为共享目标文件在每个程序中被加载的虚拟地址都不一样,要保证它不管被加载在哪都能工作),而为了实现位置无关又依赖一个前提:数据段和代码段的距离总是保持不变。

          由于不管在内存中如何加载一个目标???,数据段和代码段间的距离是不变的,编译器在数据段前面引入了一个全局偏移表GOT(Global Offset Table),被引用的全局变量或者函数在GOT中都有一条记录,同时编译器为GOT中每个条目生成一个重定位记录,因为数据段是可以修改的,动态链接器在加载时会重定位GOT中的每个条目,这样就实现了PIC。

          大体原理基本就这样,但具体实现时,对函数的处理和全局变量有所不同。由于大型程序函数成千上万,而程序很可能只会用到其中的一小部分,因此没必要加载的时候把所有的函数都做重定位,只有在用到的时候才对地址做修订。

          为此编译器引入了过程链接表PLT(Procedure Linkage Table)来实现延时绑定。PLT在代码段中,它指向了GOT中函数对应的地址,第一次调用时候,GOT存放的不是函数的实际地址,而是PLT跳转到GOT代码的后一条指令地址。

          这样第一次通过PLT跳转到GOT,然后通过GOT又调回到PLT的下一条指令,相当于什么也没做,紧接着PLT后面的代码会将动态链接需要的参数入栈,然后调用动态链接器修正GOT中的地址,从这以后,PLT中代码跳转到GOT的地址就是函数真正的地址,从而实现了所谓的延时绑定。

          对共享目标文件而言,有几个需要关注的section:

          ca5aa10c-f62b-11eb-9bcf-12bb97331649.png

          有了以上基础后,我们看一下动态链接的过程:

          1. 装载过程中程序执行会跳转到动态链接器

          2. 动态链接器自举通过GOT、.dynamic信息完成自身的重定位工作

          3. 装载共享目标文件:将可执行文件和链接器本身符号合并入全局符号表,依次广度优先遍历共享目标文件,它们的符号表会不断合并到全局符号表中,如果多个共享对象有相同的符号,则优先载入的共享目标文件会屏蔽掉后面的符号

          4. 重定位和初始化

          问题三:全局符号介入

          动态链接过程中最关键的第3步可以看到,当多个共享目标文件中包含一个相同的符号,那么会导致先被加载的符号占住全局符号表,后续共享目标文件中相同符号被忽略。当我们代码中没有很好的处理命名的话,会导致非常奇怪的错误,幸运的话立刻core dump,不幸的话直到程序运行很久以后才莫名其妙的core dump,甚至永远不会core dump但是结果不正确。

          如下图所示,main.cpp中会用到两个动态库libadd.so,libadd1.so的符号,我们把重点

          ca741d12-f62b-11eb-9bcf-12bb97331649.png

          放在Add函数的处理上,当我们以g++ main.cpp libadd.so libadd1.so编译时,程序输出“Add in add lib”说明Add是用的libadd.so中的符号(add.cpp),当我们以g++ main.cpp libadd1.so libadd.so编译时。

          程序输出“Add in add1 lib”说明Add是用的libadd1.so中的符号,这时候问题就大了,调用方main.cpp中认为Add只有两个参数,而add1.cpp中认为Add有三个参数,程序中如果有这样的代码,可以预见很可能造成巨大的混乱。

          具体符号解析我们可以通过LD_DEBUG=all 。/a.out来观察Add的解析过程,如下图所示:左边是对应libadd.so在编译时放在前面的情况,Add绑定在libadd.so中,右边对应libadd1.so放前面的情况,Add绑定在libadd1.so中。

          caa41b20-f62b-11eb-9bcf-12bb97331649.png

          运行时加载动态库:

          有了动态链接和共享目标文件的加持,Linux提供了一种更加灵活的??榧釉胤绞剑和ü峁ヾlopen,dlsym,dlclose,dlerror几个API,可以实现在运行的时候动态加载???,从而实现插件的功能。

          如下代码演示了动态加载Add函数的过程,add.cpp按照正常编译“g++ -fPIC –shared –o libadd.so add.cpp”成libadd.so,main.cpp通过“g++ main.cpp -ldl”编译为a.out。main.cpp中首先通过dlopen接口取得一个句柄void *handle。

          然后通过dlsym从句柄中查找符号Add,找到后将其转化为Add函数,然后就可以按照正常的函数使用,最后dlclose关闭句柄,期间有任何错误可以通过dlerror来获取。

          caef8b32-f62b-11eb-9bcf-12bb97331649.jpg

          问题四:静态全局变量与动态库导致double free

          在全面了解了动态链接相关知识后,我们来看一个静态全局变量和动态库纠结在一起引发的问题,代码如下,foo.cpp中有一个静态全局对象foo_,foo.cpp会编译成一个libfoo.a,bar.cpp依赖libfoo.a库,它本身会编译成libbar.so,main.cpp既依赖于libfoo.a又依赖libbar.so。

          caf98eac-f62b-11eb-9bcf-12bb97331649.jpg

          编译的makefile如下:

          cb1d0724-f62b-11eb-9bcf-12bb97331649.png

          运行a.out会导致double free的错误。这是由于在一个位置上调用了两次析构函数造成的。之所以会这样是因为链接的时候先链接的静态库,将foo_的符号解析为静态库中的全局变量,当动态链接libbar.so时,由于全局已经有符号foo_,因此根据全局符号介入,动态库中对foo_的引用会指向静态库中版本,导致最后在同一个对象上析构了两次。

          cb2b9a28-f62b-11eb-9bcf-12bb97331649.png

          解决办法如下:

          1. 不使用全局对象

          2. 编译时候调换库的顺序,动态库放在前面,这样全局只会有一个foo_对象

          3. 全部使用动态库

          4. 通过编译器参数来控制符号的可见性。

          总结:

          通过四个编译链接中碰到的问题,基本把编译链接的这些事覆盖了一遍,有了这些基础,在日常工作中应对一般的编译链接问题应该可以做到游刃有余。由于篇幅有限,文章省略了大量的细节,主要集中在大的框架原理性梳理,如果想进一步深挖相关的细节,可参与相关参考文献,以及阅读elf.h相关的头文件。

          转自:https://my.oschina.net/u/4526289/blog/4651990

          编辑:jq

          原文标题:从四个问题透析 Linux 下 C++ 编译&链接

          文章出处:【微信号:gh_3980db2283cd,微信公众号:开关电源芯片】欢迎添加关注!文章转载请注明出处。

          收藏 人收藏
          分享:

          评论

          相关推荐

          软件工程师为什么要写文档

          在大多数软件工程师对编写、使用和维护代码的抱怨中,一个常见的问题是缺乏高质量的文档。缺乏文档有什么副....
          的头像 Linux阅码场 发表于 09-09 11:26 ? 160次 阅读
          软件工程师为什么要写文档

          使用deepstream-test的范例代码修改车牌识别与遮盖

          前一篇文章提到使用deepstream-test的范例代码,修改成“车牌识别”与“遮盖(redact....
          的头像 NVIDIA英伟达企业解决方案 发表于 09-09 10:04 ? 110次 阅读
          使用deepstream-test的范例代码修改车牌识别与遮盖

          在STM32G4片内不同存储空间运行的速度差异

          最近有人问起程序在STM32G4片内不同存储空间运行的速度差异。说实在的,这个很难说死或说出个绝对的....
          的头像 茶话MCU 发表于 09-09 09:57 ? 130次 阅读
          在STM32G4片内不同存储空间运行的速度差异

          C++基础语法之volatile、assert()和sizeof()

          volatile volatile int i = 10; volatile 关键字是一种类型修饰符....
          的头像 C语言编程学习基地 发表于 09-09 09:48 ? 121次 阅读
          C++基础语法之volatile、assert()和sizeof()

          C++基础语法之inline 内联函数

          上节我们分析了C++基础语法的const,static以及 this 指针,那么这节内容我们来看一下....
          的头像 C语言编程学习基地 发表于 09-09 09:38 ? 97次 阅读
          C++基础语法之inline 内联函数

          如何使用C++语法中的volatile

          volatile volatile int i = 10; volatile 关键字是一种类型修饰符....
          的头像 C语言编程学习基地 发表于 09-09 09:38 ? 149次 阅读
          如何使用C++语法中的volatile

          C++语法中的inline内联函数详解

          上节我们分析了C++基础语法的const,static以及 this 指针,那么这节内容我们来看一下....
          的头像 C语言编程学习基地 发表于 09-09 09:33 ? 328次 阅读
          C++语法中的inline内联函数详解

          骑手保温箱追踪及温湿度监测4G设备接入机智云教程

          01 前言 利用机智云提供的通用版App即使不懂云和App开发,也可以在不用写任何代码的情况下,轻松....
          的头像 机智云开发者 发表于 09-09 09:16 ? 65次 阅读
          骑手保温箱追踪及温湿度监测4G设备接入机智云教程

          PLC编程代码

          PLC编程代码-PLC程序设计公司恒压供水控制系统的编程本程序用富士专用的FLEX PLC编程器编译,利用梯形图清晰直观地...
          发表于 09-09 08:37 ? 0次 阅读
          PLC编程代码

          独立看门狗IWDG有哪些操作步骤

          独立看门狗IWDG有哪些操作步骤? 如何去设置独立门狗分频系数的函数? ...
          发表于 09-09 06:28 ? 0次 阅读
          独立看门狗IWDG有哪些操作步骤

          【原创分享】变量的初始化技巧

          由于在嵌入式系统中必须考虑程序规模的问题,因此,对程序中的变量的初始化也需要进行慎重的考虑。在C语言中,基本数据结构(字...
          发表于 09-08 15:28 ? 303次 阅读
          【原创分享】变量的初始化技巧

          Kitronik ARCADE游戏手柄实现连连看

          连连看相信大家都玩过,但这个用Kitronik AR CADE游戏手柄来玩连连看的项目你相信是一个高....
          的头像 电子森林 发表于 09-08 11:47 ? 124次 阅读
          Kitronik ARCADE游戏手柄实现连连看

          函数信号发生器的功能及优势

          函数信号发生器是一种信号发生装置,能产生某些特定的周期性时间函数波形 ( 正弦波、方波、三角波、锯齿....
          发表于 09-08 11:35 ? 31次 阅读
          函数信号发生器的功能及优势

          继电器控制风扇程序代码

          //模拟信号端口int tempPin= 1;//数字输出端口int outpoint = 8;//温度预定值int temperature = 30;void setup(){ Serial.begi...
          发表于 09-08 07:47 ? 0次 阅读
          继电器控制风扇程序代码

          E11报警故障原因及现象

          原标题:三洋滚筒洗衣机故障代码E11、E12的处理方法yixiulaoshiw留言:请拉我进中国电器行业微信群(专业家电维修交流群)没有用...
          发表于 09-08 07:36 ? 0次 阅读
          E11报警故障原因及现象

          可摇头??胤缟仁道?/a>

          一、可摇头??胤缟仁道耄?include #include //volatile int irPin;volatile int serPin;volatile int motorPin;volatile...
          发表于 09-08 07:34 ? 0次 阅读
          可摇头??胤缟仁道? />    </a>
</div><div class=

          如何去修改语音??椋↙D3320)控制电机转动方向的代码

          ·通过语音??椋↙D3320)控制电机转动方向,其实这个语音??榈拇胪虾苋?,淘宝会提供一套完整的开发代码,我们使用者其实...
          发表于 09-08 07:07 ? 0次 阅读
          如何去修改语音??椋↙D3320)控制电机转动方向的代码

          东芝复印机故障维修详解

          实战维修 东芝复印机故障维修详解作者:IT168 流星泪痕编辑:邱灵2007-07-03 09:41评论分享【IT168 论坛采风】俗话说知根知底...
          发表于 09-08 06:50 ? 0次 阅读
          东芝复印机故障维修详解

          如何把Docker Registry迁移到Harbor

          “要如何将 docker registry 中的镜像迁移至 harbor?本文介绍了四种具体的思路和....
          的头像 马哥Linux运维 发表于 09-07 16:29 ? 225次 阅读
          如何把Docker Registry迁移到Harbor

          最为精简的一个Linux Fork炸弹解析

          转自:http://blog.saymagic.cn/2015/03/25/fork-bomb.ht....
          的头像 Linux爱好者 发表于 09-07 16:12 ? 61次 阅读
          最为精简的一个Linux Fork炸弹解析

          step-into有何作用

          step-into--作用是移动到下一个可执行的代码行。如果当前行是一个函数调用,则调试器将进入函数,并停止在函数体的第一行。step-...
          发表于 09-07 06:53 ? 0次 阅读
          step-into有何作用

          使用Intellij IDEA的一些小技巧

          https://blog.csdn.net/linsongbin1/article/details/....
          的头像 Android编程精选 发表于 09-05 15:03 ? 261次 阅读
          使用Intellij IDEA的一些小技巧

          内联汇编代码中的关键语法规则讲解

          一、基本 asm 格式 1. 语法规则 2. test1.c 插入空指令 3. test2.c 操作....
          的头像 硬件攻城狮 发表于 09-05 09:46 ? 166次 阅读
          内联汇编代码中的关键语法规则讲解

          Spark SQL的概念及查询方式

          一、Spark SQL的概念理解 Spark SQL是spark套件中一个模板,它将数据的计算任务通....
          的头像 数据分析与开发 发表于 09-02 15:44 ? 138次 阅读
          Spark SQL的概念及查询方式

          C语言代码中的extern

          在你的C语言代码中,不知能否看到类似下面的代码: 这好像没有什么问题,你应该还会想:“嗯?是啊,我们....
          的头像 STM32嵌入式开发 发表于 09-02 15:13 ? 150次 阅读
          C语言代码中的extern

          如何比较两种截然不同的编程语言的性能

          自从编程语言诞生以来,人们常常就哪种语言速度最快的问题争论不休。无论是严肃的科学研究,还是深夜酒吧的....
          的头像 嵌入式ARM 发表于 09-02 14:55 ? 151次 阅读
          如何比较两种截然不同的编程语言的性能

          你们知道指针和引用正确的使用场景吗

          先解决两个疑问 ◆ 指针和引用的不同之处是什么? ◆ 何时用用指针?何时用引用? 指针和引用的不同之....
          的头像 STM32嵌入式开发 发表于 09-02 14:37 ? 128次 阅读
          你们知道指针和引用正确的使用场景吗

          鲲鹏GCC编译器具有代表性的三方面优化特性

          编译器作为重要的基础软件之一,在各个领域都有着非常广泛的应用。比如在嵌入式领域,如何在有限的空间内丰....
          的头像 华为计算 发表于 09-02 10:48 ? 845次 阅读
          鲲鹏GCC编译器具有代表性的三方面优化特性

          Vivado调用Questa Sim或ModelSim仿真小技巧

          Vivado调用Questa Sim或ModelSim仿真中存在的一些自动化问题的解决方案。 Viv....
          的头像 FPGA之家 发表于 09-02 10:12 ? 117次 阅读
          Vivado调用Questa Sim或ModelSim仿真小技巧

          比Arduino更简单易用的开发套件ShineBlink

          Hi 机友们,我想向你推荐一个小而美的产品,一个比Arduino更简单易用的开发套件——ShineB....
          的头像 机智云物联网 发表于 09-02 10:04 ? 420次 阅读
          比Arduino更简单易用的开发套件ShineBlink

          为什么要进行单相机标定

          为什么要进行单相机标定? 广义:畸变矫正和一维和二维测量 畸变矫正: 在几何光学和阴极射线管(CRT....
          的头像 新机器视觉 发表于 09-02 09:45 ? 157次 阅读
          为什么要进行单相机标定

          Go编译器已默认启用-G=3支持泛型

          Go 项目代码仓库昨日提交和合并的一个 PR 显示,Go 语言已在 cmd/compile 中默认启....
          的头像 马哥Linux运维 发表于 09-01 15:52 ? 1056次 阅读
          Go编译器已默认启用-G=3支持泛型

          分享一个最新的的Python对象序列化方式

          许多Python标准库都有一些未被赏识的精华。其中之一是允许简单优雅的基于参数类型的函数分发。这一特....
          的头像 马哥Linux运维 发表于 09-01 15:19 ? 508次 阅读
          分享一个最新的的Python对象序列化方式

          Go常用的加密算法详细解读

          【导读】本文介绍了常用的加密算法,并对这些加密算法结合实际 golang 代码段进行了详细解读。 前....
          的头像 开关电源芯片 发表于 09-01 14:47 ? 86次 阅读
          Go常用的加密算法详细解读

          一文透析Nginx-ingress 控制器如何实现的

          主机nginx 一般nginx做主机反向代理(网关)有以下配置 upstream order{ se....
          的头像 Linux爱好者 发表于 09-01 14:44 ? 636次 阅读
          一文透析Nginx-ingress 控制器如何实现的

          代码中是数学图像解法和贪心解法

          今天讲一个贪心的老司机的故事,就是力扣第 134 题「加油站」: 题目应该不难理解,就是每到达一个站....
          的头像 新材料在线 发表于 09-01 14:14 ? 155次 阅读
          代码中是数学图像解法和贪心解法

          如何才能够翻转二叉树

          这道题目是非常经典的题目,也是比较简单的题目(至少一看就会)。 但正是因为这道题太简单,一看就会,一....
          的头像 新材料在线 发表于 09-01 11:45 ? 183次 阅读
          如何才能够翻转二叉树

          Python 代码加速运行的的小技巧

          Python 是一种脚本语言,相比 C/C++ 这样的编译语言,在效率和性能方面存在一些不足。但是,....
          的头像 Android编程精选 发表于 09-01 11:28 ? 201次 阅读
          Python 代码加速运行的的小技巧

          K8S集群服务访问失败怎么办 K8S故障处理集锦

          问题1:K8S集群服务访问失败? ? ? 原因分析:证书不能被识别,其原因为:自定义证书,过期等。 ....
          的头像 开关电源芯片 发表于 09-01 11:11 ? 172次 阅读
          K8S集群服务访问失败怎么办 K8S故障处理集锦

          SDCC编译器和FreeRTOS在C8051F上的开发的应用

          SDCC编译器和FreeRTOS在C8051F上的开发的应用(通讯电源技术2020年15期)-SDC....
          发表于 08-31 11:38 ? 18次 阅读
          SDCC编译器和FreeRTOS在C8051F上的开发的应用

          ADI-blackfin-PPI驱动TFT屏的代码-TFT-Init

          ADI-blackfin-PPI驱动TFT屏的代码-TFT-Init(电源技术投稿模版)-ADI-b....
          发表于 08-31 11:28 ? 10次 阅读
          ADI-blackfin-PPI驱动TFT屏的代码-TFT-Init

          C语言冒泡排序工程代码汇总

          C语言冒泡排序工程代码汇总
          发表于 08-30 11:06 ? 17次 阅读
          C语言冒泡排序工程代码汇总

          HFSS-API常用的基本形状和布尔操作函数

          摘要: 上节HFSS-API入门第一弹:画个Box主要是分享了调用改良hfssapi新建工程和设计文....
          的头像 知社学术圈 发表于 08-27 15:38 ? 119次 阅读
          HFSS-API常用的基本形状和布尔操作函数

          软总线是什么 剖析鸿蒙软总线超详细教程

          软总线是什么?分布式软总线是手机、平板、智能穿戴、智慧屏、车机等分布式设备的通信基座,为设备之间的互....
          的头像 华为麒麟 发表于 08-27 11:13 ? 1188次 阅读
          软总线是什么 剖析鸿蒙软总线超详细教程

          为什么有时候会写出烂代码

          本文的内容是最近我刚刚遇到的一个问题,问题代码是我自己写的,也是我自己写单元测试的时候发现的,也是我....
          的头像 深圳东裕光大 发表于 08-27 10:23 ? 210次 阅读
          为什么有时候会写出烂代码

          软件工程师加入新开发团队时需要思考的问题

          ?? 作者 | Thomas Stringer 译者 | 弯月 出品 | CSDN(ID:CSDNn....
          的头像 深圳东裕光大 发表于 08-27 10:14 ? 206次 阅读
          软件工程师加入新开发团队时需要思考的问题

          主流编程开发工具分享介绍

          俗话说的好:工欲善其事,必先利其器。一款好的开发工具对程序员来说是至关重要的,可以降低开发成本、提高....
          的头像 深圳东裕光大 发表于 08-27 10:09 ? 204次 阅读
          主流编程开发工具分享介绍

          怎么样才能让Java代码编写更规范化

          作者 | 涛姐涛哥 链接 | cnblogs.com/taojietaoge/p/11575376.....
          的头像 Android编程精选 发表于 08-27 09:31 ? 1059次 阅读
          怎么样才能让Java代码编写更规范化

          如何测量ARM Cortex-M MCU代码的执行时间

          在许多实时应用中,如电机控制、发动机控制、无线通信等时间敏感的应用,CPU可能花费不到5%的时间执行....
          的头像 奈因PCB电路板设计 发表于 08-26 09:20 ? 276次 阅读
          如何测量ARM Cortex-M MCU代码的执行时间

          网络IO的弊端以及多路复用IO的优势

          为了讲多路复用,当然还是要跟风,采用鞭尸的思路,先讲讲传统的网络 IO 的弊端,用拉踩的方式捧起多路....
          的头像 开关电源芯片 发表于 08-25 18:01 ? 459次 阅读
          网络IO的弊端以及多路复用IO的优势

          深度解读LabVIEW的彩色*obj文件读取及渲染

          随着应用场合的增多,扫描设备不仅得到物体的三维坐标信息,也得到了物体的纹理信息。*.OBJ三维文件格....
          的头像 Q哥学逆向 发表于 08-25 17:41 ? 1620次 阅读
          深度解读LabVIEW的彩色*obj文件读取及渲染

          二分搜索算法运用的框架套路

          我们前文 我作了首诗,保你闭着眼睛也能写对二分查找 详细介绍了二分搜索的细节问题,探讨了「搜索一个元....
          的头像 算法与数据结构 发表于 08-25 16:06 ? 204次 阅读
          二分搜索算法运用的框架套路

          2021年10种最受欢迎的微控制器

          MCU(微控制器)——今年的涨价王者! 无论是DIY还是专业产品,任何嵌入式电子设备的核心都是微控制....
          的头像 佐思汽车研究 发表于 08-25 14:15 ? 332次 阅读
          2021年10种最受欢迎的微控制器

          CPU如何执行代码 汇编语言教程

          学习编程其实就是学高级语言,即那些为人类设计的计算机语言。 但是,计算机不理解高级语言,必须通过编译....
          的头像 奈因PCB电路板设计 发表于 08-25 11:14 ? 152次 阅读
          CPU如何执行代码 汇编语言教程

          2021代码集结号P-TECH挑战赛获奖者名单

          P-TECH 全球挑战赛为参赛的所有青少年打开了未来的一扇窗,使他们有机会借助云计算和人工智能等前沿....
          的头像 Allegro微电子 发表于 08-24 10:55 ? 771次 阅读
          2021代码集结号P-TECH挑战赛获奖者名单
          欧美A级V片,东京热香蕉,东京热久久综合久久88 亚洲精品国产自拍-秋霞特色美国大片 龙井市| 太原市| 自贡市| 新乐市| 宝鸡市| 上犹县| 陇南市| 日照市| 泾源县| 平阴县| 米脂县| 灯塔市| 鱼台县| 定襄县| 莱西市| 葫芦岛市| 昭觉县| 高青县| 石阡县| 兴和县| 达孜县| 睢宁县| 萨嘎县| 喀喇沁旗| 辽源市| 明星| 乌海市| 嘉黎县| 五大连池市| 昌黎县| 陇南市| 水富县| 乐山市| 汶上县| 布尔津县| 保山市| 富宁县| 乌鲁木齐市| 莲花县| 民丰县| 斗六市| http://444 http://444 http://444 http://444 http://444 http://444