Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1759610
  • 博文数量: 290
  • 博客积分: 10653
  • 博客等级: 上将
  • 技术积分: 3178
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-24 23:08
文章存档

2013年(6)

2012年(15)

2011年(25)

2010年(86)

2009年(52)

2008年(66)

2007年(40)

分类: WINDOWS

2011-02-24 00:20:19

正写个罗云斌所著的聊天室程序的C语言版,编译结果是LNK1169,LNK2005,网上搜下解决问题的帖子一大堆啊,但是还没解决我的问题,缩小化问题面,问题OK.下面是过程。

先是源文件代码(为方便实验找出问题而简化的相关代码):main.c

01  #include 
02  #include "msgqueue.h"
03  #pragma comment(linker, "/subsystem:windows /RELEASE ")
04  
05  extern QUEUE_INSTANCE Queue_Instance;  //关键语句A
06  
07  int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
08  {
09      Queue_Instance.iMsgCount=0;
10      Queue_Instance.iMsgSequence=0;
11      return 0;
12  }

 下面第二个源文件:MsgQueue.h

01  #define  MAX_CHAR 256
02  #define  QUEUE_SIZE 500
03  typedef struct {
04      int iMsgId;
05      char szSender[12];
06      char szContent[MAX_CHAR];
07  } MSG_QUEUE_ITEM;
08  
09  typedef struct {
10      int iMsgCount;
11      int iMsgSequence;
12      MSG_QUEUE_ITEM MsgQueue[QUEUE_SIZE];
13  }QUEUE_INSTANCE;
14  
15  QUEUE_INSTANCE Queue_Instance={0}; //关键语句B

 下面第三个源文件:MsgQueue..c

01  #include 
02  #include "msgqueue.h"
03  

04  //Queue_Instance={0}; 
05  void InsertMsgQueue(char *lpszSender,char *lpszContent)
06  {
07      int i;
08  
09      

10      if (Queue_Instance.iMsgCount>=QUEUE_SIZE)//里面要用Queue_Instance实例
11      {
12          for (i=0;i
13          {
14              Queue_Instance.MsgQueue[i]=Queue_Instance.MsgQueue[i+1];
15          }
16          Queue_Instance.iMsgCount=i;
17      }
18  }

先发布官方解释及处理方案:

1.Linker Tools Error LNK1169

one or more multiply defined symbols found

The build failed due to multiple definitions of one or more symbols. This error is preceded by error LNK2005.

The /FORCE or /FORCE:MULTIPLE option overrides this error.

也就是"在 Project/Setting/Link/General中的 Project Options: 加入 /FORCE:MULTIPLE即可"

2.Linker Tools Error LNK2005

symbol already defined in object

The given symbol, displayed in its decorated form, was multiply defined.

Tips

One of the following may be a cause:

  • The most common cause of this error is accidentally linking with both the single-threaded and multithreaded libraries. Ensure that the application project file includes only the appropriate libraries and that any third-party libraries have appropriately created single-threaded or multithreaded versions.//到 "Project属性" -> "C/C++" -> "代码生成(code generation)" -> "运行时库(run-time library)" 项下设置应用程序为多线程,或单线程
  • The given symbol was a packaged function (created by compiling with /Gy) and was included in more than one file but was changed between compilations. Recompile all files that include the symbol. //C语言提供了一种将多个目标文件打包成一个文件的机制,这就是静态程序库(static library)。程序库为开发者带来了方便,但同时也是某些混乱的根源......略去
  • The given symbol was defined differently in two member objects in different libraries, and both member objects were used.//不同库中对同一全局对象有不同定义.
  • An absolute was defined twice, with a different value in each definition. //.//不同库中对同一全局对象有不同值.

This error is followed by fatal error LNK1169.

< src="MS-ITS://dsmsdn.chm">

< src="MS-ITS://dsmsdn.chm">

看玩MSDN的箴言,抄家伙,改为多线程运行时进行编译,得到结果:失败

 强制输出文件,得到结果:不算失败,但没解决多实例问题:warning LNK4088: image being generated due to /FORCE option; image may not run,不保险啊.

看了N篇文章,没有对策.代码少,无意间把QUEUE_INSTANCE Queue_Instance={0}; //关键语句B

中的初始化部分={0}; 移到另一个文件MsgQueue.c,进行编译,得到结果:OK

实验收获:对全局数据的初始化要放在源文件中,不能放在头文件中

以下为转载网上的经典分析文章,借鉴下:

fatal error LNK1169: one or more multiply defined symbols found

属于编译联接的常见问题之一,原因是在不同的源文件重复定义变量。比如project1有2个.c或.cpp文件,假设为a.c,b.c,如果
1:定义了相同名字的变量;
2:包含了同样的头文件(其中定义了非局部变量);  

这样在编译生成的a.obj,b.obj文件中都会为为这个同一变量 分配空间,linker会作名称检查,如果出现相同名字就会出现:

fatal error LNK1169: one or more multiply defined symbols found  

解决方法:对于第一种情况,用external关键字屏蔽其它重复定义即可; 实际上情况2更隐蔽常见,只能避免定义非局部变量。

//////////////////////////////////////////////////////////////

大家都知道,从C/C++源程序到可执行文件要经历两个阶段:(1)编译器将源文件编译成汇编代码,然后由汇编器 (assembler)翻译成机器指令(再加上其它相关信息)后输出到一个个目标文件(object file,VC的编译器编译出的目标文件默认的后缀名是.obj)中;(2)链接器(linker)将一个个的目标文件(或许还会有若干程序库)链接在一 起生成一个完整的可执行文件。

编译器编译源文件时会把源文件的全局符号(global symbol)分成强(strong)和弱(weak)两类传给汇编器,而随后汇编器则将强弱信息编码并保存在目标文件的符号表中。那么何谓强弱呢?编译 器认为函数与初始化了的全局变量都是强符号,而未初始化的全局变量则成了弱符号。比如有这么个源文件:

extern int errorno;
int buf[2] = {1,2};
int *p;

int main()
{
return 0;
}

其中main、buf是强符号,p是弱符号,而errorno则非强非弱,因为它只是个外部变量的使用声明。

有了强弱符号的概念,我们就可以看看链接器是如何处理与选择被多次定义过的全局符号:

规则1: 不允许强符号被多次定义(即不同的目标文件中不能有同名的强符号);


规则2: 如果一个符号在某个目标文件中是强符号,在其它文件中都是弱符号,那么选择强符号;


规则3: 如果一个符号在所有目标文件中都是弱符号,那么选择其中任意一个;

由上可知多个目标文件不能重复定义同名的函数与初始化了的全局变量,否则必然导致LNK2005和LNK1169两种链接错误。可是,有的时候我们并没有在自己的程序中发现这样的重定义现象,却也遇到了此种链接错误,这又是何解?嗯,问题稍微有点儿复杂,容我慢慢道来。


众 所周知,ANSI C/C++ 定义了相当多的标准函数,而它们又分布在许多不同的目标文件中,如果直接以目标文件的形式提供给程序员使用的话,就需要他们确切地知道哪个函数存在于哪个 目标文件中,并且在链接时显式地指定目标文件名才能成功地生成可执行文件,显然这是一个巨大的负担。所以C语言提供了一种将多个目标文件打包成一个文件的 机制,这就是静态程序库(static library)。开发者在链接时只需指定程序库的文件名,链接器就会自动到程序库中寻找那些应用程序确实用到的目标模块,并把(且只把)它们从库中拷贝 出来参与构建可执行文件。几�

阅读(12808) | 评论(0) | 转发(0) |
0

上一篇:Fuzzing or fuzz

下一篇:QT layout 使用总结

给主人留下些什么吧!~~