首页
学习
活动
专区
工具
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.1K60

    一文领略链接与装载

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

    93830

    CSAPP---第七章-链接

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

    85610

    地址无关码

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

    98620

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

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

    1.9K30

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

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

    24120

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

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

    1.8K40

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

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

    75410

    objdump命令解析

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

    4.6K21

    《逆袭进大厂》第三弹之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.8K81

    认识目标文件符号

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

    1.5K40

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

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

    1.1K20

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

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

    3.9K110

    LD_LIBRARY_PATH和LIBRARY_PATH区别

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

    1.2K40

    程序编译、链接、装载与运行

    静态链接过程分为两步 扫描所有的目标文件,获取它们每个段长度、位置和属性,并将每个目标文件符号表符号定义和符号引用收集起来放在一个全局符号表,建立起可执行文件到目标文件段映射关系 读取目标文件段数据...而a.c则不一样,因为在a.c变量shared和函数swap都没有定义在当前文件,因此编译后产生目标文件不存在它们地址信息,所以编译器需要把它们放在定位表,等到链接再到其它目标文件中找到对应符号信息之后对其进行定位...当使用到标准内容,链接器会对用户目标文件和标准进行链接,得到最终可执行文件。 链接过程控制 链接默认情况下生成是一个ELF文件,这在Linux操作系统上是符合我们要求。...,保存操作系统内核数据,用户进程无权访问该地址 Stack(栈) 用于实现程序函数调用,在下一节程序运行我们会详细了解栈工作方式 Heap(堆) 为了保存在程序运行时(而非编译)产生全局变量注...中断处理函数寄存器 eax 获取到系统调用编号,根据系统调用编号找到指定系统调用函数 系统调用函数约定好寄存器获取所需参数,系统调用函数根据参数开始执行 系统调用执行完毕后,将系统调用结果存放在用户程序有权访问区域

    1.3K10

    深入iOS系统底层之静态介绍

    通常情况下在编写程序时会引用其他源文件或者动态定义函数或者类方法以及全局变量,因此在编译阶段所有的外部引用符号地址是无法被确定,此时生成目标文件段(Segment)节(Section...)外部函数调用指令操作数部分以及外部全局变量符号地址值都将是0。...这个定位表每个条目会将所有需要进行定位指令或者数据访问位置信息以及引用外部符号信息记录起来,以便在链接进行更新处理。下面的图表展示了这个结构: ?...我们知道在程序链接需要读取目标文件符号表信息才能决定其他目标文件引用符号信息是否真实存在,当其他目标文件引用符号信息不存在或者找不到时就会报经典符号信息不存在错误: Undefined...☞场景1: 当你头疼于你程序尺寸而需要删减一些无用代码,那么对于删除静态多余代码是一个不错选择,你需要做就是通过ar命令将静态目标文件逐个删除,然后再做链接,直到应用不报链接错误为止

    1.3K52
    领券