[编译报错解决]duplicate symbol _base64_encode解决办法

本文介绍了解决iOS项目在模拟器上运行时出现的重复符号错误问题,通过修改第三方库zbar中的base64_encode函数名称并进行相应调整,最终实现项目在模拟器上的正常运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目不支持模拟器运行,报下面的错。
duplicate symbol _base64_encode in:

.../libzbar.a(symbol.o)

.../tencentOpenAPI(base64.o)



说的很清楚,就是这两个库中都定义了_base64_encode,所以编译器就会报错重复定义。
查了网上的一些方法,需要用到libtool什么的等等一些工具,或者删除_all_load等,都没什么用。
于是,只有一个办法了,去寻找源码,但是腾讯这种sdk,肯定是不会给源码的,只有去找libzbar的源码了。
先去下载zbar的源码      http://zbar.sourceforge.net/download.html

如图1,打开工程
如图2,找到symbol.c

如图3 找到 base64_encode这个方法
找到 base64_encode这个方法,更改这个方法名,比如,我改成了 base64_en,同时,找到调用这个方法的那一行代码,修改为 base64_en。然后再分别在真机和模拟器下运行工程,找到这2个libzbar.a文件。至于是否合并为通用的.a。就看你自己了。
合并的方法网上也很多了,非常简单。
打开终端,输入命令   lipo -create XXX(路径名)/Release-iphoneos/libzbar.a  XXX(路径名)/Release-iphonesimulator/libzbar.a  -output   XXX(输出的路径名)/libzbar.a 
然后,导入这个libzbar.a,就可以在模拟器上运行项目了。
是不是很简单呢?呵呵。。。。
当然,我感觉这是比较偷懒或者简便的方法。如果没有源码的话,就要用到那些个什么麻烦的要死的工具了。
觉得不好,勿喷。和谐和谐。哈哈哈。。

[ 此帖被angellixf在2014-01-03 22:12重新编辑 ]

图片:1.png 
图片:2.png 
图片:3.png 
<think>我们遇到了一个链接错误:`ld.lld:error:duplicatesymbol:'_write_api_document@12'`。这个错误表明在链接过程中发现了两个同名的符号(函数或变量)被定义了两次。具体来说,这个符号`_write_api_document@12`在`basesource.o`和`basesource_1.o`两个目标文件中都被定义了。###错误原因分析:1.**重复定义**:在C语言中,同一个函数或全局变量在多个源文件中被定义,会导致链接器在合并目标文件时发现多个定义,从而报错。2.**函数签名**:`_write_api_document@12`这个符号可能是函数`write_api_document`经过名称修饰(namemangling)后的形式。`@12`表示这个函数调用时使用12个字节的参数(可能是3个4字节参数,具体取决于调用约定)。在Windows环境下,编译器可能会使用这种修饰方式(如stdcall调用约定)。3.**可能的原因**:-在多个源文件中都定义了名为`write_api_document`的函数。-头文件中包含了`write_api_document`函数的定义(而非声明),然后这个头文件被多个源文件包含,导致每个源文件都有一份定义。-在源文件中定义了一个全局变量,然后在头文件中用`extern`声明,但是不小心在某个源文件中定义了两次。###解决方法:1.**检查函数定义**:确保`write_api_document`函数只在一个源文件中定义一次。如果多个源文件都需要使用这个函数,应该在头文件中声明它(使用`extern`),然后在其中一个源文件中定义。2.**检查头文件**:确保头文件中只有函数的声明,而没有函数的定义(除非是内联函数)。例如:-正确声明(在头文件中):```cexternvoidwrite_api_document(intparam1,intparam2,intparam3);```-定义(只能在一个源文件中):```cvoidwrite_api_document(intparam1,intparam2,intparam3){//函数体}```3.**检查重复的全局变量**:如果`_write_api_document@12`实际上是一个全局变量,同样要确保只在一个地方定义,其他地方用`extern`声明。4.**使用static关键字**:如果这个函数确实需要在多个文件中使用不同的实现(但函数名相同),那么可以将它们声明为`static`,这样每个文件中的函数作用域仅限于本文件,不会在链接时冲突。但通常我们不希望这样,因为这里显然是同一个函数被重复定义了。5.**检查文件包含**:查看`basesource.c`和`basesource_1.c`两个源文件,确认是否都包含了同一个定义`write_api_document`的头文件。如果是,请将头文件中的定义改为声明。###示例代码修正:假设我们有一个头文件`api.h`,它不应该包含函数定义:```c//api.h#ifndefAPI_H#defineAPI_H//只声明函数,不定义voidwrite_api_document(inta,intb,intc);#endif```然后在`basesource.c`中定义函数:```c//basesource.c#include"api.h"voidwrite_api_document(inta,intb,intc){//实现代码}```而`basesource_1.c`中只使用函数,不定义:```c//basesource_1.c#include"api.h"voidsome_other_function(){write_api_document(1,2,3);}```###其他注意事项:-如果这个函数是第三方库中的函数,那么可能是在链接时重复链接了同一个库的不同版本,或者在不同的库中都有定义。需要检查链接的库。-在Windows中,如果使用dll,也可能出现导出符号冲突。###总结:这个错误通常是由于在多个地方定义了同一个函数或全局变量导致的。解决方法是确保每个函数和全局变量在整个项目中只定义一次。§§相关问题§§:1.C语言中,`extern`关键字的作用是什么?2.在C语言中,如何避免头文件被重复包含?3.链接器在链接多个目标文件时,如何处理符号重复定义的问题?4.在C语言中,`static`关键字用于函数时有什么作用?</think>### 问题分析 链接错误 `duplicate symbol: _write_api_document@12` 的根本原因是 **同一个符号在多个目标文件中被重复定义**。具体分析如下: 1. **符号冲突**: - 函数 `write_api_document` 在 `basesource.o` 和 `basesource_1.o` 两个目标文件中都被定义 - Windows 编译器会对函数名进行修饰(如 `@12` 表示参数总大小),但核心符号名相同 2. **常见原因**: - 在头文件中直接定义了函数实现(而非声明) - 多个源文件包含同一个带函数定义的 `.c` 文件 - 误将函数定义写在头文件且未使用 `static` 或 `inline` --- ### 解决方法 #### 方案1:分离声明与定义(推荐) **步骤:** 1. 创建头文件 `api.h`(仅包含声明): ```c // api.h #pragma once void write_api_document(int arg1, int arg2, int arg3); // 仅声明 ``` 2. 在单独源文件实现函数 `api.c`: ```c // api.c #include "api.h" // 唯一实现 void write_api_document(int arg1, int arg2, int arg3) { // 具体实现... } ``` 3. 其他文件通过头文件调用: ```c // basesource.c #include "api.h" void func_a() { write_api_document(1, 2, 3); } // basesource_1.c #include "api.h" void func_b() { write_api_document(4, 5, 6); } ``` #### 方案2:使用 `static` 限制作用域 若需在每个文件保留独立实现: ```c // basesource.c static void write_api_document(int a, int b, int c) { // 文件内私有 /* 实现A */ } // basesource_1.c static void write_api_document(int x, int y, int z) { // 文件内私有 /* 实现B */ } ``` #### 方案3:使用内联函数(C99+) ```c // common.h inline void write_api_document(int p1, int p2, int p3) { // 内联实现(每个包含文件独立展开) } ``` --- ### 关键预防措施 1. **头文件规则**: - 头文件只放**声明**(`extern` 变量、函数原型) - 实现代码必须放在 `.c` 文件中 2. **编译检查**: ```bash gcc -c basesource.c -o basesource.o gcc -c basesource_1.c -o basesource_1.o nm basesource.o | grep write_api_document # 检查符号定义 ``` 3. **链接顺序**: 确保链接器命令中每个目标文件只包含一次定义: ```bash gcc basesource.o basesource_1.o api.o -o program.exe ``` --- ### 错误深层原理 | 阶段 | 行为 | 错误触发点 | |-------------|-------------------------------|------------------------| | 编译 | 每个 `.c` 独立生成目标文件 | 函数被多次编译进不同.o | | 链接 | 合并所有符号表 | 发现两个同名全局符号定义 | | 名称修饰 | Windows 添加 `_` 前缀和 `@n` 后缀 | 修饰后仍相同 | > 📌 注:在 Windows 调用约定中,`@12` 表示函数有 12 字节参数(3个int),不同编译器修饰规则可能不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值