首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

从库访问可执行文件中定义的全局变量时出现重定义错误

问题描述:从库访问可执行文件中定义的全局变量时出现重定义错误。

解决方案:当从库中访问可执行文件中定义的全局变量时,可能会出现重定义错误。这是因为在编译过程中,可执行文件和库被分别编译成独立的目标文件,并且每个目标文件都有自己的命名空间。因此,如果可执行文件和库中定义了相同名称的全局变量,就会发生重定义错误。

要解决这个问题,可以采取以下几种方法:

  1. 使用静态变量:将全局变量定义为静态变量,这样它们将在编译过程中具有内部链接(internal linkage),从而避免了重定义错误。静态变量只能在定义它们的源文件中访问,因此库文件和可执行文件中定义的同名静态变量不会发生冲突。
  2. 使用命名空间:将可执行文件和库中的全局变量分别放在不同的命名空间中,确保它们的名称不会发生冲突。通过在定义全局变量时添加命名空间前缀,可以避免重定义错误。
  3. 使用静态库:将全局变量放在静态库中,可执行文件通过链接静态库来使用这些全局变量。静态库中的全局变量只会被编译一次,因此不会出现重定义错误。
  4. 使用外部链接:如果确实需要在可执行文件和库中共享同名的全局变量,可以将这些全局变量声明为extern,并将它们放在单独的源文件中。然后,在需要使用这些全局变量的地方,通过包含该源文件来引用这些全局变量。这样可以确保在链接过程中只有一个全局变量的定义,避免了重定义错误。

总结:在从库访问可执行文件中定义的全局变量时出现重定义错误时,可以使用静态变量、命名空间、静态库或外部链接等方法来解决问题。具体选择哪种方法取决于具体的应用场景和需求。

(注意:以上答案不包含任何云计算品牌商,根据问题描述给出了解决方案,仅供参考。)

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

GDB读取动态库中定义的全局变量错误

最近看了一篇getopt使用的文章,为了追踪其执行的逻辑,于是采用GDB挂载调试的方式进行查看。但却出现了GDB打印全局变量optind的时候出现错误。...也就是动态库中存在全局变量的时候,在编译阶段已经在程序的.BSS段中预留了控件给动态库中的全局变量,然后当程序初始化的时候,会拷贝动态库中的全局变量到程序预留的.BSS段控件;其他所有的动态库,也将访问通过前面所说的....BSS段中的全局变量来访问原先动态库中定义的全局变量。...回到原先的问题,那么GDB打印出来并不是程序中.BSS通过Copy Relocation产生的全局变量optind, 而是打印的libc.so中原有的变量的值。...首先我们通过"Info var optind"查看下optind相关的信息,可以看到两处指名了optind的出处,第一处其实说明了这个是在libc.so中定义的,而gdb默认打印的也是libc.so中定义的

2.1K30

《深入理解计算机系统》(CSAPP)读书笔记 —— 第七章 链接

.symtab:一个符号表,它存放在程序中定义和引用的函数和全局变量的信息。一些程序员错误地认为必须通过-g选项来编译一个程序,才能得到符号表信息。...然后,链接器将运行时内存地址赋给新的聚合节,赋给输人模块定义的每个节,以及赋给输人模块定义的每个符号。当这一步完成时,程序中的每条指令和全局变量都有唯一的运行时内存地址了。 重定位节中的符号引用。...多个目标文件可以定义相同的符号,而链接器用来悄悄地解析这些多重定义的规则可能在用户程序中引入微妙的错误。   多个目标文件可以被连接到一个单独的静态库中。链接器用库来解析其他目标模块中的符号引用。...许多链接器通过从左到右的顺序扫描来解析符号引用,这是另一个引起令人迷惑的链接时错误的来源。 加载器将可执行文件的内容映射到内存,并运行这个程序。...在加载时,加载器将部分链接的可执行文件映射到内存,然后调用动态链接器,它通过加载共享库和重定位程序中的引用来完成链接任务。

2.6K31
  • 《程序员的自我修养》第三章学习笔记

    从结构上说,是编译后的可执行文件,只不过还没有经过链接 3.1 目标文件的格式 1,可执行文件的格式: Windows下的PE  和   Linux下的ELF 2,从广义上说,目标文件与可执行文件的格式几乎是一样的...3.5.2 特殊符号 1,ld链接器产生可执行文件时,会给我们定义很多符号(没有在自己的程序中定义),但是可以直接声明并且引用它,我们称之为特殊符号。...3.5.5 弱符号与强符号 1,多个目标文件含有相同名字的全局符号的定义,在链接时将会出现符号重复定义的错误。 2,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。...5,弱引用与强引用: 强引用:假如链接时没找到该符号的定义,链接器就会报符号未定义错误。 弱引用:假如链接时没找到该符号的定义,链接器不会报错,默认其为0或是一个特殊值。...7,弱符号和弱引用对库来说非常有用,比如库中定义的弱符号可以被用户定义的强符号所覆盖。

    1.2K60

    一文领略链接与装载

    与弱符号对应的还有弱引用,如果弱引用的符号有定义,链接器决议该符号,如果弱引用的符号未定义,链接器不认为是一个错误。...链接器扫描完所有的重定位表,所有的重定位入口符号都能在全局符号表中找到,否则链接器就会报符号未定义错误。...最简单的方式就是直接为进程划分物理内存区域,这会有很多缺点: 地址空间不隔离。程序直接访问物理地址很容易出现进程间相互影响。 内存使用效率低。...指令通过相对寻址就能找到数据段中的 GOT,从而找到需要访问变量的目标地址。 共享对象的全局变量 定义在模块内部的全局变量,有一种特殊情况:extern int global;。...这时编译器其实判断不了这个符号是定义在内部还是外部的,就不知道该不该分配空间。在共享库编译时,编译器处理方式是默认把定义在模块内部的全局变量当做定义在其它模块,通过 GOT 实现。

    98831

    CSAPP---第七章-链接

    这样的选项调用链接器,在遇到多重定义的全局符号时,触发一个错误,或者使用-Werror选项,它会把所有的警告都变成错误, ---- 静态库 我们可以通过链接器读取一组可重定位文件,并把它们链接起来,形成一个可执行文件...注意:如果定义一个符号的库出现在引用这个符号的目标文件之前,那么引用就不能被解析,链接会失败。...---- 重定位条目 当汇编器生成一个目标模块时,它并不知道数据和代码最终将放在内存中的什么位置。它也不知道这个模块引用的任何外部定义的函数或者全局变量的位置。...除了一些头部信息,在加载过程中没有任何从磁盘到内存的数据复制。直到 CPU 引用一个被映射的虚拟页时才会进行复制,此时,操作系统利用它的页面调度机制自动将页面从磁盘传送到内存。...多个目标文件可以定义相同的符号,而链接器用来悄悄地解析这些多重定义的规则可能在用户程序中引入微妙的错误。 多个目标文件可以被连接到一个单独的静态库中。链接器用库来解析其他目标模块中的符号引用。

    92310

    地址无关码

    第一种是模块内部的函数调用、跳转等; 第二种是模块内部的数据访问,比如模块中定义的全局变量、静态变量。 第三种是模块外部的函数调用、跳转等。...第四种是模块外部的数据访问,比如其他模块中定义的全局变量。 类型一 模块内部调用或跳转等 这4种情况中,第一种类型应该是最简单的,那就是模块内部调用。...类型三 模块间数据访问 模块间的数据访问比模块内部稍微麻烦一点,因为模块间的数据访问目标地址要等到装载时才决定,比如上面例子中的变量b,它被定义在其他模块中,并且该地址在装载时才能确定。...ELF共享库在编译时,默认都把定义在模块内部的全局变量当作定义在其他模块的全局变量,也就是说当作前面的类型四,通过GOT来实现变量的访问。...但是装载时重定位的共享对象的运行速度要比使用地址无关代码的共享对象快,因为它省去了地址无关代码中每次访问全局数据和函数时需要做一次计算当前地址以及间接地址寻址的过程 对于可执行文件来说,默认情况下,如果可执行文件是动态链接的

    1K20

    深入理解编译、链接和运行(obj文件组成格式分析,可执行文件组成格式分析)

    128MB的保留区,所以会出现段错误。...(3)共享库 如果程序中用到了库函数,如printf、scanf、puts、gets等。则在共享库中包含了这些函数的定义。...(4)栈 函数运行用到的栈 内核空间的分析: (1)ZONE_DMA:直接内存访问,正常情况下,磁盘中的数据到达主存需要进过存储器的层次结构,需要经过CPU。....obj文件组成格式的分析,着重看 现在新的问题出现了: (2.1)既然.obj文件中都没有存储.bss段的信息,那么在程序中那些初始化为0的全局变量和未初始化的局部变量它是怎么识别它们的?...: 符号解析:所有obj文件符号表中对符号引用的地方都要找到符号定义的地方,否则就会出现链接错误。

    2K30

    我与C语言二周目邂逅vlog——8.编译和链接

    编译器在生成目标文件时,有些符号(如外部函数)并没有具体的地址信息,因此需要链接器来进行符号解析。 重定位:将目标文件中的地址信息进行调整,使得最终的可执行文件中的所有地址都指向正确的位置。...类型错误:变量的类型不匹配,如将 int 变量赋值给 char 指针。 未定义的变量:使用未定义的变量或函数。 7.2 链接错误 链接错误是在链接阶段出现的问题,通常与符号解析和重定位有关。...例如: 未定义的引用:目标文件中引用了一个未定义的符号,例如函数的声明找不到对应的实现。 重复定义:多个目标文件中存在相同的全局变量或函数实现,导致符号冲突。...7.3 链接顺序 在使用静态库时,链接的顺序可能会影响最终的链接结果。通常,链接器会按顺序扫描库文件,因此被依赖的库应放在依赖它们的库之后,否则可能出现未定义引用的问题。 8....9.2 静态链接库与动态链接库 静态链接库(.a 文件):静态链接库在链接时被嵌入到可执行文件中,生成的可执行文件独立性强,但体积较大。

    11710

    《计算机系统2》学习笔记

    符号解析: 建立符号引用和定义之间的联系。 重定位: 为每一个引用确定地址。 链接时间:编译时、加载时、运行时。...符号解析 作用 将每个符号引用与它输入的可重定位目标文件的符号表中的一个确定的符号定义关联起来。 强符号 函数和已经初始化的全局变量。 弱符号 未初始化的全局变量。 规则 不允许存在同名强符号。...静态库链接 静态库 定义 将相关可重定位目标模块打包成一个单独的文件。...重定位 重定位由两步组成:重定位节和符号定义,重定位节中的符号引用。 重定位节和符号定义 赋予指令和全局变量唯一的运行时内存地址。...库函数被合并到可执行目标文件中,磁盘上存放着数千个可执行文件,造成磁盘空间的极大浪费。 程序员需关注是否有函数库的新版本出现,并须定期下载、重新编译和链接,使用不便且编译耗时。

    25620

    C++系列:链接器是如何工作的

    除非理解了链接器是怎样解析引用、什么是类库、链接器是怎样使用类库来解析引用等原理,这类错误经常令人困惑。 2.理解链接器可以减少严重编程错误的出现频率。...Linux链接器在解析符号引用时所作的决策会静默地影响程序的正确性。比如,在默认情况下,如果错误地定义了多个全局变量,链接器是不会报错的。但是生成的程序会表现出令人困惑的行为,且这种程序是很难调试的。...当定义了静态变量或者静态函数时,到底会意味着什么?等等 4.理解链接过程有助于理解其他重要的系统概念。...链接器的作用:简单的讲,链接器的工作就是解析未定义的符号引用,将目标文件中的占位符替换为符号的地址。链接器还要完成程序中各目标文件的地址空间的组织,这可能涉及重定位工作。...这里还会有个新名词,什么是重定位呢? To:重定位,就是将每个符号和内存中的一个位置关联起来,然后修改代码中所有对这些符号的引用,使它们指向这个内存位置。

    1.8K40

    后台开发:核心技术与应用实践 -- 编译与调试

    比如#include、#define 等,主要处理规则如下所述: 将所有的 `#define~ 删除,并且展开所有的宏定义 还有 #undef,则将取消对某个宏的定义,使以后该串的出现不再被替换...链接过程主要包括了地址和空间分配、符号决议和重定位等这些步骤。 静态链接过程如图所示,每个模块的源代码文件经过编译器编译成目标文件,目标文件和库一起链接形成最终可执行文件。 ?...系统调用的错误码 :系统调用并不直接返回错误码,而是将错误码放入一个名为 errno的全局变量中。如果一个系统调用失败,你可以读出 errno 的值来确定问题的所在。...C和C++ 的程序,首先在编译时,必须要把调试信息加到可执行文件中。...需要强调的是,以上内容都是位于程序的可执行文件中,内核在调用 exec 函数启动该程序时从源程序文件中读人数据段属于静态内存分配 未初始化数据段(.bss segment):通常是指用来存放程序中未初始化的全局变量的一块内存区域

    77010

    ELF文件从形成到加载轮廓

    可以在运行时由多个程序共享加载,节省内存空间,但需要确保运行环境中有正确的库文件支持。 内核转储(Core Dumps) 用于存储当前进程的执行上下文,通常在进程因信号(如段错误)触发时生成。...记录每个段的起始位置、偏移量和长度,因为这些段在二进制文件中紧密排列,程序头表提供必要的描述信息以区分和加载这些段。 主要用于可执行文件和共享库,在加载时由操作系统或动态链接器使用。...链接阶段可能出现错误,如“undefined reference”(未定义引用),通常因缺少库文件或符号定义不一致引起。...printf:未定义符号,标记为 U,需从标准库 libc 中解析。...外部引用(如 printf)标记为未定义(UND),链接时从标准库(如 libc)解析。 查看与验证:使用 nm、readelf -s 查看符号表,结合源码和目标文件理解符号的定义和引用。

    6710

    objdump命令解析

    .data:已初始化的全局C变量。局部C变量在运行时被保存在栈中,既不出现在.data中,也不出现在.bss节中。 .bss:未初始化的全局C变量。....symtab:一个符号表(symbol table),它存放在程序中被定义和引用的函数和全局变量的信息。一些程序员错误地认为必须通过-g选项来编译一个程序,得到符号表信息。...注意,可执行目标文件中并不需要重定位信息,因此通常省略,除非使用者显式地指示链接器包含这些信息。 .rel.data:被模块定义或引用的任何全局变量的信息。...一般而言,任何已初始化全局变量的初始值是全局变量或者外部定义函数的地址都需要被修改。....debug:一个调试符号表,其有些表目是程序中定义的局部变量和类型定义,有些表目是程序中定义和引用的全局变量,有些是原始的C源文件。只有以-g选项调用编译驱动程序时,才会得到这张表。

    4.7K21

    《逆袭进大厂》第三弹之C++提高篇79问79答

    ; 4、在被调函数中,从ebp的位置处开始存放被调函数中的局部变量和临时变量,并且这些变量的地址按照定义时的顺序依次减小,即:这些变量的地址是按照栈的延伸方向排列的,先定义的变量先入栈,后定义的变量后入栈...“重定义”错误。...1) C++中的异常情况: 语法错误(编译错误):比如变量未定义、括号不匹配、关键字拼写错误等等编译器在编译时能发现的错误,这类错误可以及时被编译器发现,而且可以及时知道出错的位置及原因,方便改正。...在使用静态库的情况下,在编译链接可执行文件时,链接器从库 中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件。...,把需要用到的对应动态链接库中的部分提取出来,连接到可执行文件中去,使可执行文件在运行时不需要依赖于动态链接库; 2) 动态编译的可执行文件需要附带一个动态链接库,在执行时,需要调用其对应动态链接库的命令

    2.2K30

    动态链接的步骤与实现

    从这一步开始,动态链接器代码中才可以使用自己的全局变量和静态变量。 实际上在动态链接器的自举代码中,除了不可以使用全局变量和静态变量之外,甚至不能调用函数,即动态链接器本身的函数也不能调用。...“ Now life is sane",可以想象动态链接器的作者在此时大舒一冂气,终于完成白举了,可以自由地调用各种函数并且随意访问全局变量了, 2....,从而导致程序莫名其妙的错误。...如果进程的可执行文件也有“init”段,那么动态链接器不会执行它,因为可执行文件中的“init”段和“ finit”段由程序初始化部分代码负责执行,我们将在后面的“库”这部分详细介绍程序初始化部分。...自举的过程需要十分的小心谨慎,因为有很多限制.这个我们在前面已经介绍过了。完成自举之后就可以调用其他函数并访问全局变量了。

    1.4K20

    ELF文件及android hook原理

    符号解析与重定位 编译器在将”a.c”编译成指令时,它如何访问”shared”变量?如何调用”swap”函数?...对于第2步,当操作系统捕获到缺页错误时,它应该知道程序当前所需的页在可执行文件中的哪一个位置。 这种映射关系是保存在操作系统内部的一个数据结构VMA。...页错误 在上面的例子中,程序的入口地址为0x08048000,当CPU开始打算执行这个地址的指令时,发现页面0x08048000~0x08049000(虚拟地址)是个空页面,于是它就认为这是一个页错误...,然后把控制权再还给进程,进程从刚才页错误的位置重新开始执行。...当代码需要引用该全局变量时,可以通过GOT中相对用的项间接引用,它的基本机制如下图。 ? 当指令中需要访问变量b时,程序会先找到GOT,然后根据GOT中变量所对应的项找到变量的目标地址。

    3.9K81

    认识目标文件的符号

    特殊符号 当我们使用 ld 作为链接器来链接生产可执行文件时,它会为我们定义很多特殊的符号,这些符号并没有在你的程序中定义,但是你可以直接声明并且引用它,我们称之为特殊符号。...在后来 UNIX 和 C 被发明后,当 C 程序使用汇编语言编写的库和目标文件时,不可以使用这些库中定义的函数和变量的名字作为符号名,否则产生冲突。...下面以 C++ 为例,看一下现代高级编程语言对符号的修饰方法。 C++ 支持函数重载,两个相同名字的函数 func(int) 和 func(double) 编译时并不会报重定义错误。...多个目标文件中含有相同名字全局符号的定义,那么这些目标文件链接的时候将会出现符号重复定义的错误。...但是当我们运行这个可执行文件时,会发生运行错误。因为当main函数试图调用foo函数时,foo函数的地址为0,于是发生了非法地址访问的错误。

    1.6K40

    C++编译与链接(2)-浅谈内部链接与外部链接

    发现每次写技术博客时,都会在文章开头处花费一番功夫 ...从前,有一个程序员....他的名字叫magicsoar 为什么有时会出现aaa已在bbb中重定义的错误?...最后让我们回到文章开头处的那几个问题吧 为什么有时会出现aaa已在bbb中重定义的错误?...答:你可能在不同的cpp中重复定义了一个具有外部链接的函数或变量,链接器在链接时找到了多个一样的函数或变量定义 为什么有时会出现无法解析的外部符号?...答:你可能只提供了函数或变量的声明,没有提供其定义,或者声明和定义的函数原型不一致,链接器没有找到其定义在哪里,所以在链接环节出现了无法解析的外部符号的错误 为什么有的内联函数的定义需要写在头文件中呢?...,便会出现无法解析的外部符号的错误 为什么对于模板,声明和定义都要写在一起呢?

    4K110

    链接加载原理及ELF文件格式

    接着你会对程序出现的一些异常情况束手无策,对内核代码中的一些用法不能理解,对makefile中的一些实现不知所云。...重定位表(Relocation): 有了符号表,就需要有人对符号表进行引用,在程序的执行过程中对全局变量的引用、跳转、调用函数,这些都涉及到相应的符号引用。...同样加载的过程中还需要重定位操作,需要将外部链接库中的函数和变量和本程序中的引用链接起来,但是由于加载过程中代码已经处于运行状态,使用链接过程中同样的重定位手段有些不合适。...所以加载过程中的重定位,使用了一种改良的重定位手段:即通过两张间接访问表来屏蔽掉重定位带来的对代码的修改,访问外部数据使用GOT,访问外部程序使用PLT。...elf文件格式 Linux环境下,三种类型的执行文件都可以使用elf格式来表示:可重定位文件(即编译生成但是未连接的文件)、动态库文件、可执行文件。

    1.2K20

    LD_LIBRARY_PATH和LIBRARY_PATH的区别

    通常一个目标文件中至少有两个段: 代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。 数据段:主要存放程序中要用到的各种全局变量或静态的数据。...静态库的优点在于: 程序员不需要显式的指定所有需要链接的目标模块,因为指定是一个耗时且容易出错的过程; 链接时,连接程序只从静态库中拷贝被程序引用的目标模块,这样就减小了可执行文件在磁盘和内存中的大小。...默认的动态库搜索路径/lib /usr/lib/ /usr/local/lib 静态链接(编译时) 链接器将函数的代码从其所在地(目标文件或静态链接库中)拷贝到最终的可执行程序中。...为创建可执行文件,链接器必须要完成的主要任务: 符号解析:把目标文件中符号的定义和引用联系起来; 重定位:把符号定义和内存地址对应起来,然后修改所有对符号的引用。...动态链接器(ld-linux.so)链接程序在运行过程中根据记录的共享对象的符号定义来动态加载共享库,然后完成重定位。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。

    1.3K40
    领券