6

您好行业资深人士,

我是一名大三学生,开始了我的第一次暑期编程实习,但我的想法有点过头了。我工作的公司从另一家公司购买了一个巨大的应用程序,该公司自 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)

我的理解是,当解决方案中的不同项目使用不同的运行时库编译时,通常会发生这种情况。我的解决方案中有 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)

在阅读了有关LNK2001LNK2019的 MSDN 页面后,我意识到我不知道发生了什么。这些不是他们在学校教我们如何处理的问题。我知道我的数据结构,仅此而已。我是如何走到现在的,这超出了我的想象!

根据我有限的知识,这些模块的各种调试和发布版本似乎都纠缠在预处理器指令和#includes 的网络中。在整个解决方案的环境变量、文件名、宏等方面,几乎每个头文件和源文件中都有许多嵌套的#ifdef 检查和#define 语句。通过对我的编译器设置进行微小的更改,我似乎将程序的大部分重定向到具有非常不同函数定义的不同库。这是我对正在发生的事情的模糊概念理解。

我觉得在我有机会解决这些编译器错误之前,我需要更好地了解这段代码的工作原理。为此,我一直在尝试逐行浏览许多文件,以查看它们的引导位置、范围内的对象和变量等等。不幸的是,这并没有让我走得太远,因为对外部函数的每次调用都是模棱两可的,而且我无法通过预处理器的混乱来了解应该调用任何给定函数的哪个版本。

我一直在寻找神奇的解决方案来绘制程序并尝试理解它。我尝试了一个名为Doxygen,但要么我不知道如何正确使用它,要么它和我一样被预处理器的东西弄糊涂了。

我的问题是:
我剩下的选择是什么?

在这一点上,这是一个折腾:
a.)转换专业
b.)跳桥

这些选择都不会帮助我更好地理解这个代码库并让它编译。有没有人有更好的想法?类似的经历?圣人智慧分享?

非常感谢,
-亚历克斯

4

3 回答 3

3

看来您正在使用 CodeProject 中的 CResizableSheet 和 CResizeablePage。如果您使用的是从该页面编译的静态库,您可以尝试下载源代码并使用匹配的 /MDd 设置对其进行编译,并使用它在项目的链接器输入部分中输出的 .lib。我还建议进行全部清理(转到构建->批量构建->全选然后单击清理),然后再次尝试构建以确保一切都是最新的。

于 2012-07-13T22:49:42.673 回答
2

我听说护理是一个很棒的项目......

冒着迂腐的风险,您要解决的是链接器错误,而不是编译器错误。我对此的基本方法是创建一个新的解决方案,并开始一次添加一个项目,让每个项目依次构建。

我也会认真考虑尽可能地标准化每个项目的设置。最简单的方法是在新解决方案中创建空项目,并将现有代码复制到其中。

首先,您应该假设以下设置(与 MFC 相关):

调试:在共享 DLL 中使用 MFC,/MDd
发布:在共享 DLL 中使用 MFC,/MD

MDd 和 MD 是相同的模式,但是其中一个链接指向带有额外调试信息的调试库。

那么你所能做的就是一次做一个项目。请注意,如果您按照建议创建新解决方案,则需要重建项目之间的依赖关系树。(右键单击一个项目并选择“依赖项”,您会明白我的意思。)

当您在执行此操作时遇到问题时,您应该与工作场所的高级开发人员交朋友 =)。

于 2012-07-13T22:52:53.220 回答
1

使用相同的运行时库编译所有内容。故事结局。

于 2012-07-16T21:39:02.187 回答