【发布时间】:2012-07-13 21:56:34
【问题描述】:
各位行业资深人士,
我是一名大三学生,开始了我的第一次暑期编程实习,但我的想法有点过头了。我工作的公司从另一家公司购买了一个巨大的应用程序,该公司自 90 年代初以来一直在缓慢地扩展和修改它。该解决方案包含超过 200,000 行代码,分布在 300 多个文件中。据称整个解决方案是按照 ANSI-C++ 标准编写的。代码几乎完全没有文档记录,其中大部分在我看来就像象形文字。最终,我的工作是将此代码移植到嵌入式 Linux。目前,我的工作只是在 Windows XP 上使用 Visual Studio 2008 进行编译。
今天,我遇到了像这样的链接器错误:
libcmtd.lib(sprintf.obj) : error LNK2005: _sprintf already defined in msvcrtd.lib(MSVCR90D.dll)
我的理解是,当解决方案中的不同项目使用不同的runtime libraries 编译时,通常会发生这种情况。我的解决方案中有 6 个项目。其中 4 个设置为使用多线程调试 DLL 运行时库 (/MDd) 进行编译,其中一个设置为使用多线程调试库 (/MTd) 进行编译,其中一个设置为使用多线程 dll 运行时库 (/MD)。收到此错误消息后,我尝试的第一件事是将 /MTd 和 /MD 开关更改为 /MDd,以便使用相同的运行时库编译所有内容。不幸的是,这导致了 afx.h 中的以下错误:
fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]
经过一番挖掘,我发现它已经告诉了我需要做什么。我继续将项目属性->配置属性->常规下的“使用 MFC”选项更改为“在共享 DLL 中使用 MFC”。此时我开始收到几十个未解决的外部错误,例如:
dataPropertySheet.obj : error LNK2019: unresolved external symbol "public: __thiscall CResizableSheet::CResizableSheet(unsigned short const *,class CWnd *,unsigned int)" (??0CResizableSheet@@QAE@PBGPAVCWnd@@I@Z) referenced in function "public: __thiscall CdataPropertySheet::CdataPropertySheet(unsigned short const *,class CWnd *,unsigned int)" (??0CdataPropertySheet@@QAE@PBGPAVCWnd@@I@Z)
ResizableLib.lib(ResizablePage.obj) : error LNK2001: unresolved external symbol "public: virtual int __thiscall CWnd::Create(char const *,char const *,unsigned long,struct tagRECT const &,class CWnd *,unsigned int,struct CCreateContext *)" (?Create@CWnd@@UAEHPBD0KABUtagRECT@@PAV1@IPAUCCreateContext@@@Z)
在阅读了 LNK2001 和 LNK2019 上的 MSDN 页面后,我意识到我不知道发生了什么。这些不是他们在学校教我们如何处理的问题。我知道我的数据结构,仅此而已。我是如何走到现在的我已经超出了我的想象!
根据我有限的知识,这些模块的各种调试和发布版本似乎都纠缠在预处理器指令和#includes 的网络中。在整个解决方案的环境变量、文件名、宏等方面,几乎每个头文件和源文件中都有许多嵌套的#ifdef 检查和#define 语句。通过对我的编译器设置进行微小的更改,我似乎将程序的大部分重定向到具有非常不同函数定义的不同库。这是我对正在发生的事情的模糊概念理解。
我觉得在我有机会解决这些编译器错误之前,我需要更好地了解这段代码的工作原理。为此,我一直在尝试逐行浏览许多文件,以查看它们的引导位置、范围内的对象和变量等等。不幸的是,这并没有让我走得太远,因为对外部函数的每次调用都是模棱两可的,而且我无法通过预处理器了解应该调用哪个版本的任何给定函数。
我一直在寻找神奇的解决方案来规划程序并尝试理解它。我试过一个叫Doxygen,但要么我不知道如何正确使用它,要么它和我一样被预处理器的东西弄糊涂了。
我的问题是:
我还有哪些选择?
在这一点上,这是一个折腾:
a.) 转专业
b.) 跳桥
这些选择都不会帮助我更好地理解这个代码库并让它编译。有没有人有更好的想法?类似的经历?圣人智慧分享?
非常感谢,
-亚历克斯
【问题讨论】:
-
处理此类配置混乱的一种方法是创建一个具有所需配置的空项目,然后比较设置。因此,使用 /MD 和共享 MFC dll 创建一个新项目,确保它可以编译,并将其与您的非编译项目进行比较。
-
我不熟悉 Microsoft 运行时库,但我认为在这种情况下最好的做法是向您的老板解释问题的严重性。把这个问题变成一个 15 分钟的幻灯片演示。要非常酷和专业。不要使用诸如“巨大”或“噩梦”之类的词,否则他们会认为您在夸大其词,并且不要提及您自己的经验不足(“...我不知道发生了什么...”)否则他们会认为这就是问题所在。请记住,您不是抱怨辛勤工作的孩子,您是告知患者危及生命状况的专家。
-
Beta 提出了一个很好的观点,尽管我认为 15 分钟的演示文稿从 =) 开始会有点多。相反,你应该问问你的老板你应该在公司找谁来帮助你了解你面临的错误。
-
他们现在知道了,他们和我一样困惑。至少知道在这个行业工作了 30 多年的人仍然可以像这样撞墙,这让人松了一口气。我现在有权联系原始软件供应商,请求帮助编译他们的代码。我想我会一直用头撞墙,直到我听到源头的回复。 :-/
标签: c++ mfc doxygen lnk2019 lnk2001