C缺陷与陷阱 — 8 编译与链接

目录

1 程序的编译过程

2 动态链接的优缺点

2.1 动态链接的优点

2.2 动态链接的缺点

2.3 只使用动态链接

3 函数库链接的5个特殊秘密

4 警惕Interpositioning

5 产生链接器报告文件


1 程序的编译过程

程序的编译过程是将源代码转换成计算机可以执行的机器代码的过程。这个过程通常包括以下几个主要步骤:

(1)预处理(Preprocessing预处理是编译过程的起始步骤,主要针对源代码文件中的预处理指令进行相应处理。

  • 宏定义展开(#define):通过#define指令定义宏,预处理时会按照定义规则对代码里相应的宏进行文本替换,比如定义#define PI 3.14,代码中出现PI的地方就会被替换成3.14。
  • 条件编译指令(#ifdef、#ifndef、#endif 等):条件编译指令可依据是否定义了特定宏等条件,来决定代码段是否参与后续编译。
  • 包含头文件(#include:预处理器会把指定头文件的全部内容插入到源代码中相应的位置。例如,#include <stdio.h>会将标准输入输出头文件里的内容(像printf、scanf等函数的声明等)添加进来。

(2)编译(Compilation):将预处理后的源代码转换为中间代码,并进行优化以及最终生成目标代码的过程,涉及多个子环节。

  • 词法分析:编译器会把预处理后的源代码当作字符流,将其拆解成一个个单词(tokens),这些单词涵盖了编程语言里的关键字(如 C 语言中的int、if、for等)、标识符(变量名、函数名等)、常量(整数常量、浮点数常量、字符常量等)、运算符(+、-、*、/等)以及界符(;、{、}等)。例如对于代码int num = 10;,词法分析器能准确分解出 “int”(关键字)、“num”(标识符)、“=”(运算符)、“10”(常量)和 “;”(界符),为后续分析提供基础元素。
  • 语法分析:基于词法分析得到的单词,编译器依据编程语言既定的语法规则构建语法树,以树形结构清晰呈现程序的语法构成以及语句、表达式之间的层次关系。比如针对if语句if (condition) { statement; },语法树会将if作为根节点,其下细分出条件表达式condition节点以及语句块statement节点。一旦代码存在语法错误,像括号缺失或者关键字拼写有误等情况,语法分析阶段就能检测出来。
  • 语义分析:主要检查程序语义的正确性,包含检查变量是否正确定义与使用、类型是否匹配等关键方面。例如在表达式int a = 3.14;中,语义分析环节会察觉到将双精度浮点数赋值给整型变量属于类型不匹配的错误;同时也会处理变量的作用域问题,确保变量仅在其定义的有效范围内被正确访问,例如函数内部定义的局部变量不能在函数外部随意调用。
  • 中间代码生成:部分编译器会生成中间代码,它处于源语言与目标机器语言之间,具备平台无关性优势,常见形式有三地址码等。例如对于表达式a = b + c,可能生成类似t1 = b + c; a = t1的三地址码形式,这种中间表示形式利于后续进一步的优化以及适配不同目标机器的代码生成工作。
  • 代码优化:编译器会对生成的中间代码实施优化操作,旨在提升程序的执行效率,优化手段多种多样。比如常量折叠,像int a = 2 + 3;可直接优化为int a = 5;,减少不必要的运算;死代码消除,即去除那些永远不会被执行的代码,避免占用资源;循环展开,通过将循环体展开一定次数来降低循环控制方面的开销等,通过这些优化策略让程序在执行时间和存储空间利用上更为高效。
  • 目标代码生成:这是编译阶段的收尾环节,会把经过优化的中间代码(若有)或者直接把处理后的代码转换为目标机器的语言,这种目标代码可能是汇编语言形式,也有可能直接就是机器代码(二进制形式),具体取决于编译器的设计以及编译的配置。

(3)汇编(Assembly):汇编器(Assembler)将汇编语言代码转换成机器代码。汇编语言是一种低级语言,它更接近于机器代码,但仍然包含一些助记符,使得程序员更容易理解和编写。

(4)链接(Linking):链接过程旨在将编译生成的多个目标文件(通常以.o(在 Linux 等系统下)或.obj(在 Windows 系统下)为扩展名)与各类库文件以及其他相关目标文件进行合并整合,最终生成一个单一的可执行文件(像.exe(Windows 系统)或.out(Linux 等系统)文件)。

  • 符号解析:目标文件中包含诸多符号,例如函数名、全局变量名等,链接器的关键任务之一就是确定这些符号的具体定义位置。比如一个源文件中调用了另一个源文件里定义的函数int add(int a, int b),在链接时,链接器必须精准找到该函数实现代码所在的目标文件,若无法找到某个符号的定义,就会出现如 “undefined reference to 'add'” 这类链接错误提示。
  • 重定位:目标文件中的代码与数据部分往往包含一些相对地址或者虚拟地址,在链接阶段,需要依照最终可执行文件的整体布局对这些地址进行相应调整。例如,目标文件中某个函数调用指令原本采用相对地址来指向被调用函数,当链接器把多个目标文件组合到一起时,就需要重新计算这些相对地址,以保障函数调用能够准确无误地跳转到被调用函数的实际内存位置,确保程序执行的正确性。
  • 库链接:程序在开发过程中通常会借助一些库来实现额外的功能,像标准 C 库、数学库等,链接器要把这些库文件与目标文件妥善链接起来。库分为静态库和动态库两种类型,静态库是多个目标文件的集合,链接时,链接器会把程序实际使用的静态库中目标文件的代码和数据全部复制到最终可执行文件里。动态库链接时不会把库文件全部代码复制到可执行文件中,而是在程序运行需调用其函数时,由操作系统加载动态库并完成相应函数调用操作。

(5)加载(Loading):加载器(Loader)负责将可执行文件加载到内存中,进而启动程序的执行流程。

2 动态链接的优缺点

2.1 动态链接的优点

动态链接是一种更为现代的方法,能够更加有效地利用磁盘空间,动态链接只需要处理对动态库的引用关系,不需要像静态链接那样将库的全部代码合并到可执行文件中,因此在编译和链接阶段时间也会缩短。尽管单个可执行文件约启动速度稍受影响,但动态链接可以从两个方面提高性能:

(1)动态链接可执行文件比功能相同的静态链接可执行文件的体积小,相应的会节省磁盘空间和虚拟内存。静态链接在生成可执行文件时,会把程序所用到的函数库(比如标准 C 库、数学库等)中相关目标文件的代码和数据全部复制到可执行文件里面,即便它可能只调用了库中的少数几个函数,而动态链接则不同,动态链接的可执行文件中只是包含了对相应动态库中函数和变量等的引用信息,真正的函数库代码并不嵌入到可执行文件里。

(2)当多个可执行文件都动态链接到同一个特定函数库时,在运行期间,操作系统只会把这个函数库加载到内存中一次,形成一个单独的拷贝。例如,在 Linux 系统下,多个应用程序都动态链接了libc.so(C 标准库对应的动态库),那么在内存中只会存在一份libc.so的实例。操作系统内核通过内存映射机制来实现共享,它会将这份已加载到内存中的函数库映射到每个需要使用它的进程的虚拟地址空间中。各个进程虽然感觉像是自己独占了这个函数库,但实际上它们共享的是同一份物理内存中的代码和数据,这样就避免了重复加载相同的函数库内容到内存里。如果可执行文件是静态链接的,每个文件都将拥有一份函数库的拷贝,显然极为浪费。

动态链接使得函数库的版本升级更为容易。新的函数库可以随时发布,只要安装到系统中,旧的程序就能够自动获得新版本函数库的优点而无需重新链接。

2.2 动态链接的缺点

动态链接是一种“just-in-time(JIT)”链接,这意味着程序在运行时必须能够找到它们所需要的函数库。链接器通过把库文件名或路径名植入可执行文件中来做到这一点。这意味着,函数库的路径不能随意移动。如果把程序链接到/user/ib/libthread.so库,那么就不能把该函数库移动到其他的目录,除非在链接器中进行特别说明。否则,当程序调用该函数库的函数时,就会在运行时导致失败,给出这样一条错误信息:

ld.so.1:main:fatal:libthread.so:can't open file:errno 2

当在一台机器上编译完程序后,把它拿到另一台不同的机器上运行时,也可能出现这种

情况。执行程序的机器必须具有所有该程序需要链接的函数库,而且这些函数库必须位于在链接器中所说明的目录。对于标准系统函数库而言,这并不成问题。

2.3 只使用动态链接

动态链接现在是运行System V release4UNIX的计算机所采用的缺省设置。从作用上

看,静态链接现已过时,只能静静躺在一边睡大觉。

使用静态链接的最大危险在于将来版本的操作系统可能与可执行文件所绑定的系统函数库不兼容。如果应用程序静态链接于版本N的操作系统中,当把程序运行于版本N+1的操作系统上时,它可能会立即崩溃,也可能出现一个不明显的错误。我们无法保证早期版本的系统函数库能够在后期版本的系统上正确地运行。事实上,反过来考虑倒还比较保险一点。但是,如果应用程序动态链接到版本N的系统函数库,当它运行于版本N+1的操作系统上时,它就会正确选取N+1版本的系统函数库。

相反,静态链接的应用程序不得不针对每个新版本的操作系统进行重新生成以保证能够运行。而且,有些函数库(扣libaio.so,libdl.so,libsys..so,libsolv.so以及librpcsvc.so等)只能以动态链接的形式使用。如果在应用程序中使用了这些函数库中的任何一个,你的程序就必须使用动态链接。最好的策略就是所有的应用程序都使用动态链接,这就可以避免可能产生的问题。

3 函数库链接的5个特殊秘密

当使用函数库时,需要掌握5个基本的、不明显的约定。绝大多数C语言书籍或手册对此并没有作出清楚的解释。

(1)动态库文件的扩展名是“.so”,而静态库文件的扩展名是“.a

按照约定,所有动态库的文件名的形式是libname.so。这样,线程函数库便被称作libthread.so。静态库的文件名形式是libname.a,共享archive的文件名形式是libname.sa。共享archive只是一种过渡形式,帮助人们从静态库转变到动态库,现在已过时。

(2)通过-lthread选项,告诉编译链接到libthread.so

传给C编译器的命令行参数里并没有提到函数库的完整路径名,甚至没有提到在函数库目录中该文件的完整名字!函数库名字的呈现形式是把 “lib” 部分和文件的扩展名去掉,然后在前面添加一个 “l”。例如,对于名为 libthread.so 的函数库,在命令行中就是通过 -lthread 选项来告知编译器去链接它。

gcc -o thread_demo thread_demo.c -lthread

(3)编译器期望在确定的目录找到库

这里,你可能会疑惑,编译器是怎么知道该往什么目录寻找函数库呢?就像存在一种特殊的规则用于查找头文件一样,编译器也自有办法来寻找函数库。它查看一些特殊的位置,如在/usr/ib中查找函数库,例如线程库位于usr/Iib/libthread.so。

编译器选项-Lpathname告诉链接器一些其他的目录,如果命令中加入了-l选项,链接器就往这些目录查找函数库。系统中存在几个环境变量,LD LIBRARY_PATH和

LD_RUN_PATH,也是用于提供这类信息。出于安全性、性能和创建/运行独立性方面的考虑,使用环境变量的做法现在己经不提倡。一般还是在链接时使用-Lpathname和-Rpathname选项。

(4)观察头文件,确认所使用的函数库

你有可能遇见的另一个关键问题是“我怎么知道必须链接到哪些函数库?如果观察程序中的源代码,就会发现自己调用了一些自己不曾实现的函数。例如,如果程序跟三角有关,可能会调用像sin()和cos()这样的函数,它们可以在math函数库中找到。

一个很好的建议就是可以观察程序所使片的#include指令。在程序中所包舍的每个头文件都可能代表一个必须链接的库,但需要注意头文件的名字通常并不与它所对应的函数库名相似。函数库链接所存在的另一个不一致性就是函数库所包含的某个函数的原型可能与其他头文件中所声明的函数的原型一样。

(5)与提取动态库中的符号相比,静态库中的符号提取的方法限制更严

最后,在动态链接和静态链接的链接语义上还存在一个额外的大区别,它经常会迷惑不够仔细的用户。

假设我们有一个简单的 main.c 文件,里面调用了一些来自标准 C 库的函数(比如 printf 函数,其所在的库在动态链接时会被自动处理),使用 gcc 编译器进行动态链接编译生成可执行文件的命令示例如下:

gcc main.c -o dynamic_executable

这里,-o 选项指定了输出的可执行文件名是 dynamic_executable。在这个过程中,像 printf 这类库符号所在的动态库(例如 libc.so 等)会在运行时被加载到程序的虚拟地址空间,使得程序可以找到并执行相应的函数,并且多个链接在一起的文件都可以访问到这些动态库中的符号。

同样针对上述 main.c 文件进行静态链接,并且假设有一个自定义的静态库 mylib.a,同时假设 main.c 中调用了 mylib.a 里定义的函数以及标准 C 库中的函数(比如 printf),按照正确顺序进行静态链接编译生成可执行文件的命令示例如下:

gcc main.c mylib.a -o static_executable

这里必须保证先写 main.c ,再写 mylib.a ,因为静态链接时符号是从左到右按顺序解析的,如果写成:

gcc mylib.a main.c -o static_executable

可能就会出现问题,因为在处理 mylib.a 这个静态库时,链接器一开始还没遇到 main.c 里对 mylib.a 中符号的未定义引用(也就是还不知道需要从 mylib.a 里找哪些符号),那么就可能不会正确地从 mylib.a 中提取对应的符号,导致后续链接 main.c 时出现符号未定义等错误。

如果在自己的代码之前引入静态库,又会带来另一个问题。因为此时尚未出现未定义的符号,所以它不会从函数库中提取任何符号。接着,当目标文件被链接器处理时,它所有的对函数库的引用都将是未实现的!

例如,像 “cc -lm main.c” 这样进行静态链接(math 库常以静态链接的 archive 形式存在用于提高运行时性能),若程序使用了如 sin 等数学函数,会得到 “Undefined first referenced symbol in file sin main.o ld:fatal:Symbol referencing errors.No output written to a.out” 这样的错误信息。

为从 math 库中提取所需符号,需要写成 “cc main.c -lm” 这种形式,让文件先包含未解析的引用。个人都习惯了通用的命令形式<命令><选项><文件>,所以让链接器采用<命令><文件><选项>这样的约定是很容易引起混淆。

4 警惕Interpositioning

Interpositioning 是一种通过编写与函数同名的函数来取代库函数行为的技术。可以在特定程序中拦截库函数的调用,以便检查参数、返回值或跟踪程序的执行流程,有助于快速定位问题。在某些情况下,可以通过优化同名的用户函数来提高特定操作的执行效率。

使用Interpositioning需要格外小心。很容易发生自己代码中某个符号的定义取代函数库中的相同符号的意外。这意味着不仅自己对该库函数的调用会被自己版本的函数调用所取代,而且所有调用该库函数的系统调用也会被用户函数取代。例如,假设程序中使用了一个库函数 printf 进行输出,而程序员不小心编写了一个同名的 printf 函数。在这种情况下,程序中所有原本应该调用库函数 printf 的地方都会调用用户自定义的 printf 函数,这可能会导致输出结果与预期不符,甚至可能引发程序错误。

当编译器注意到库函数被另外一个定义覆盖时,它通常不会给出错误信息。这是因为 C 语言遵循“程序员所做的都是对的”的设计哲学,编译器认为这是程序员的意图。这种特性使得在使用 Interpositioning 时,错误很难被及时发现。程序员可能在不经意间使用了这种技术,却没有意识到自己已经覆盖了库函数,从而导致程序出现难以察觉的错误。

由于 Interpositioning 具有较高的风险,只有在确实需要进行调试或提高效率时才考虑使用。对于新手来说,应尽量避免使用这种技术,以免伤害自己。

5 产生链接器报告文件

可以在ld程序中使用“-m”选项,让链接器产生一个报告,里面包括了被Interpose

的符号的说明。通常,带“-m”选项的ld会产生一个内存映射或列表,显示在可执行文件中的什么地方放入了哪些符号。它同时显示了同一个符号的多个实例,通过查看报告的内容,用户可以判断是否发生了Interpositioning。假如你有一个待链接的目标文件叫 main.o,想生成包含符号相关信息的报告,命令可能如下:

ld -m main.o -o output_executable

ld程序中的“-D”选项是随SunOS5.3引入的,日的是提供更好的链接-编辑调试。这个选项允许用户显示链接-编辑过程和所包含的输入文件。如果需要监视从archive中提取对象的过程,这个选项尤其有用,同时可用于显示运行时绑定信息。同样针对 main.o 这个目标文件,想要查看链接编辑过程和涉及的输入文件,命令示例如下:

ld -D main.o -o another_executable

ld是一个复杂的程序,还有很多其他选项和约定未在此处说明。对于绝大多数应用来说,这些说明已经足够了。如需知道更多有关它的知识,下面提供了四条途径,按其复杂程度分列如下:

  • 使用1dd命令,列出可执行文件的动态依赖集。这条命令会告诉你动态链接的程序所需要的函数库。
  • ld程序的-Dhelp选项能提供一些信息,有助于查找链接过程中出现的问题。
  • 查看ld程序的在线文档。

 

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

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

相关文章

Harmony Next开发Navigation页面跳转

概述 Harmony Next开发Navigation页面跳转 知识点 Navigation通过NavPathStack路由跳转Navigation以弹窗的方式打开NavDestination页面Menu配置 组件 NavTest Entry Component struct NavTest {Provide pageInfos: NavPathStack new NavPathStack()Builder PageMap(name…

大模型系列4--开源大模型本地部署到微调(WIP)

背景 一直想真正了解大模型对硬件资源的需求&#xff0c;于是准备详细看一篇视频&#xff0c;将核心要点总结记录下。本文内容参考视频&#xff1a;保姆级教程&#xff1a;6小时掌握开源大模型本地部署到微调&#xff0c;感谢up主 训练成本 训练 > 微调 > 推理训练GPT…

仿《公主连结》首页场景的制作(附资源包)

先看效果&#xff08;主要实现点击按钮切换图片&#xff0c;未解锁按钮弹出提示&#xff0c;点击过后播放动画&#xff09; 预备知识&#xff08;单例模式&#xff0c;携程&#xff0c; Resources.Load加载资源的方式&#xff09; 资源准备&#xff08;底部按钮7个图标&#x…

Redis - 集合 Set 及代码实战

Set 类型 定义&#xff1a;类似 Java 中的 HashSet 类&#xff0c;key 是 set 的名字&#xff0c;value 是集合中的值特点 无序元素唯一查找速度快支持交集、并集、补集功能 常见命令 命令功能SADD key member …添加元素SREM key member …删除元素SCARD key获取元素个数SI…

基于Llamaindex的网页内容爬取实战

目的 本文不关注如何解析网页 html 元素和各种 python 爬虫技术&#xff0c;仅作为一种网页数据的预处理手段进行研究。Llamaindex 也并不是爬虫技术的集大成者&#xff0c;使用它是为了后续的存查一体化。 安装依赖 pip install llama-index-readers-web # pip install llam…

《九重紫》逐集分析鉴赏第一集(下)

主标题&#xff1a;《九重紫》一起追剧吧 副标题&#xff1a;《九重紫》逐集分析鉴赏第一集&#xff08;下&#xff09;/《九重紫》逐集分析鉴赏1 接上回分解&#xff0c;窦昭和宋墨都安置城外万佛寺 交谈没一会儿&#xff0c;天还未亮&#xff0c;兵临寺下 记住这个人&…

Introduction to NoSQL Systems

What is NoSQL NoSQL database are no-tabular非數據表格 database that store data differently than relational tables 其數據的存儲方式與關係型表格不同 Database that provide a mechanism機制 for data storage retrieval 檢索 that is modelled in means other than …

图论【Lecode_HOT100】

文章目录 1.岛屿数量No.2002.腐烂的橘子No.9943.课程表No.2074.实现Trie&#xff08;前缀树&#xff09;No.208 1.岛屿数量No.200 class Solution {public int numIslands(char[][] grid) {if (grid null || grid.length 0) {return 0;}int numIslands 0;int rows grid.len…

【深度学习量化交易9】miniQMT快速上手教程案例集——使用xtQuant获取基本面数据篇

我是Mr.看海&#xff0c;我在尝试用信号处理的知识积累和思考方式做量化交易&#xff0c;应用深度学习和AI实现股票自动交易&#xff0c;目的是实现财务自由~目前我正在开发基于miniQMT的量化交易系统。 在前几篇的文章中讲到&#xff0c;我正在开发的看海量化交易系统&#xf…

网络层IP协议(TCP)

IP协议&#xff1a; 在了解IP协议之前&#xff0c;我们市面上看到的"路由器"其实就是工作在网络层。如下图&#xff1a; 那么网络层中的IP协议究竟是如何发送数据包的呢&#xff1f; IP报头&#xff1a; IP协议的报头是比较复杂的&#xff0c;作为程序猿只需要我们重…

Xcode

info.plist Appearance Light 关闭黑暗模式 Bundle display name 设置app名称&#xff0c;默认为工程名 Location When In Use Usage Description 定位权限一共有3个key 1.Privacy - Location When In Use Usage Description 2.Privacy - Location Always and When In U…

【CSS in Depth 2 精译_079】第 13 章:渐变、阴影与混合模式概述 + 13.1:CSS 渐变效果(一)——使用多个颜色节点

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 13 章 渐变、阴影与混合模式】 ✔️ 13.1 渐变 ✔️ 13.1.1 使用多个颜色节点&#xff08;一&#xff09; ✔️13.1.2 颜色插值13.1.3 径向渐变13.1.4 锥形渐变 文…

地下管线三维建模,市面上有哪些软件

1. 地下管线&#xff1a;城市“生命线” 地下管线是城市的重要基础设施&#xff0c;包括供水、排水、燃气、热力、电力、通信等管线&#xff0c;它们如同城市的“生命线”&#xff0c;支撑着城市的正常运转。如果缺乏完整和准确的地下管线信息&#xff0c;施工破坏地下管线的事…

说说你对java lambda表达式的理解?

大家好&#xff0c;我是锋哥。今天分享关于【说说你对java lambda表达式的理解?】面试题。希望对大家有帮助&#xff1b; 说说你对java lambda表达式的理解? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Java Lambda 表达式是 Java 8 引入的一项重要特性&#…

网易云信荣获“HarmonyOS NEXT SDK星河奖”

近日&#xff0c;鸿蒙生态伙伴 SDK 开发者论坛在北京举行。 网易云信凭借在融合通信领域的技术创新和鸿蒙生态贡献&#xff0c;荣获鸿蒙生态“HarmonyOS NEXT SDK星河奖”。 会上&#xff0c;华为鸿蒙正式推出 SDK 生态繁荣伙伴支持计划&#xff0c;旨在为 SDK 领域伙伴和开发…

电压调整电路汇总

目录&#xff1a; 一、LDO线性稳压器 1、LM1117 2、NCV33275 3、TLE42764 4、TPS7B67xx-Q1 5、总结 二、DCDC转换器 1、LM2576 2、MC34063A 3、总结 原文件下载移步&#xff1a;LDO-DCDC的仿真与Altium原理图 一、LDO线性稳压器 1、LM1117 LM1117 是一款在 800mA 负…

2024美亚杯资格赛复现

参考&#xff1a; 2024“美亚杯”第十届中国电子数据取证大赛资格赛参考WP 2024美亚杯个人资格赛WP 第十届美亚杯个人赛内存和优盘解答 2024年美亚杯个人赛 资格赛 wp_2024美亚杯个人赛-CSDN博客 历年赛题及解析 - 美亚杯 第一次打&#xff0c;感觉就是题量很大&#xff…

练12:双指针

欢迎大家订阅【蓝桥杯Python每日一练】 专栏&#xff0c;开启你的 Python数据结构与算法 学习之旅&#xff01; 文章目录 前言1 同向扫描2 反向扫描3 同向扫描与反向扫描的对比4 例题分析2.1 回文判定2.2 美丽的区间2.3 挑选子串 前言 双指针是一种常用于数组和链表类问题中&a…

360智脑张向征:共建可信可控AI生态 应对大模型安全挑战

发布 | 大力财经 人工智能的加速发展&#xff0c;有力推动了社会的数智化转型&#xff1b;与此同时&#xff0c;带来的相关安全风险也日益凸显。近日&#xff0c;在北京市举办的通明湖人工智能开发与应用大会上&#xff0c;360智脑总裁张向征以“大模型安全研究与实践”为主题&…

6.数据建模和数据检索及权限检查

总学习目录请点击下面连接 SAP ABAP开发从0到入职&#xff0c;冷冬备战-CSDN博客 目录 1.数据建模和ABAP字典的透明表 现实产品到数据库数据过程 飞行数据模型 做一个简单的引用。 从旅行社来看&#xff1a; 对于开发人员&#xff1a; 透明表 结构体和透明表 在系统中…