如何跟踪此链接器错误?

How do I follow this linker error?

提问人:Alex Jansen 提问时间:7/19/2012 最后编辑:CommunityAlex Jansen 更新时间:7/19/2012 访问量:1296

问:

我正在做我的第一个实习,仍然试图在Visual Studio 2008上编译这个可怕的东西。我花了一周的时间研究 IDE 设置和 Windows SDK 安装,我认为我不会在这个方向上取得任何进展。每个人都在这里度假,我没有高级工程师可以求助。帮帮我 Stack Overflow,你是我唯一的希望!

今天,我试图跟踪特定的错误,所以我知道为什么一切都会崩溃。也许那时我会更好地了解如何解决它。在过去的几个小时里,我一直在研究这个问题:

6>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)

我的理解是,在我正在使用的 ResizableLib 项目内部找不到 CWnd::Create 函数。我想我会找到调用它的文件,并跟踪包含内容,看看它是否应该在调用它的位置有CWnd::Create的定义。我首先在整个项目 (alt+E+F+I) 中搜索 Create(因为我认为这将获取调用 Create 函数的每个实例。我发现了其他几个以 Create 结尾的函数调用,但只有一个似乎在调用 Create 函数本身:

ResizableGrip.cpp(127): BOOL bRet = m_wndGrip.Create(WS_CHILD | WS_CLIPSIBLINGS

所以。。。我打开了ResizableGrip.cpp并查看了包含的内容。文件的第一行是:

#include "stdafx.h"

我想我会去看看那个文件,看看是否有 CWnd::Create 的函数声明,或者可能是它的某种继承版本。包含此文件没有预处理器条件(因为此程序中的许多其他点都有),因此我认为可以肯定地说 stdafx.h 将被包含。为了弄清楚将包含哪个 stdafx.h 文件(stdafx.h 文件通常用于什么?我到处都能看到它们!),我首先查看了与 ResizableGrip.cpp 文件相同的目录,因为我相信编译器首先在与包含文件相同的目录中查找,然后再检查项目中的其他包含路径,最后是主 Visual Studio VC++ 设置中列出的包含路径。这是正确的吗?无论如何,有一个 StdAfx.h 文件位于同一目录中,所以我得出结论,这将是包含的文件。该文件的前几行如下所示:

#if !defined(AFX_STDAFX_H__0A781DD9_5C37_49E2_A4F5_E517F5B8A621__INCLUDED_)
#define AFX_STDAFX_H__0A781DD9_5C37_49E2_A4F5_E517F5B8A621__INCLUDED_
#pragma message("StdAfx CommonClasses/ResizableLib")
#ifdef INC_DEBUG
#pragma message("In ResizeLib::StdAfx.h") 
#endif

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#if _MSC_VER >= 1300
#define  WINVER      0x0500
#define _WIN32_WINNT 0x0500
#endif

#define VC_EXTRALEAN        // Exclude rarely-used stuff from Windows headers

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>         // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT

我承认我并不完全理解这里发生的所有预处理器事情,但由于没有围绕 #include 的条件,我认为它也被包括在内。项目目录中没有 afxwin.h 文件,因此我查看了该项目的其他包含。唯一指定的位置是 ....\COMMON,所以我去了两个目录,找到了 COMMON 文件夹,然后查找了 afxwin.h。那里什么都没有,所以我在 IDE 设置中查看了 VC++ 目录包含。第一个列表是:$(WindowsSdkDir)\include,所以我查找了 WindowsSdkDir 环境变量,当然它不存在。我也检查了注册表。没有骰子。最终,我发现可以通过单击项目配置窗口中文本字段最右端出现的省略号 (...) 之一并展开“宏”窗格来解析这些符号名称。通过这样做,我发现$(WindowsSdkDir)指向:C:\Program Files\Microsoft SDKs\Windows\v6.0A\,所以我去了那里,打开了Include文件夹,没有找到afxwin.h文件。$(FrameworkSDKDir)include 指向与 $(WindowsSdkDir)\include 相同的位置,因此我继续执行 Visual Studio VC++ 目录包含列表中的下一行:$(VCInstallDir)atlmfc\include,解析为 C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\ 我最终找到了 afxwin.h。在这个文件中,最后有一个名为 Cwnd 的类,其中一个名为 Create 的函数定义如下:

virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);

我不知道这些参数是什么,但我的假设是,这是链接器最初抱怨的函数的极度重新定义的版本:

CWnd::Create(char const *,char const *,unsigned long,struct tagRECT const &,class CWnd *,unsigned int,struct CCreateContext *)

否则,编译器不会在链接器接管之前将其捕获为函数的不同版本吗?实际上,现在我想到了(因此我发帖的全部原因),我想我所做的只是以与解决编译器错误相同的方式遍历代码。我做对了吗?这东西是个怪物,我只是在这里猜测。

所以再说一次,就像标题所说的那样,你应该如何遵循链接器错误?有没有与我在这里所做的类似的过程?MSDN 文章听起来像是当代码工作正常并且编译器以某种方式设法丢失 .obj 文件或 .lib 文件时会发生此错误。我怎样才能让它再次指向正确的位置?

呸 -亚历克斯

C++ Visual-Studio-2008 链接器错误未 解决 - 外部 LNK2001

评论

0赞 sarnold 7/19/2012
你必须把这个怪物移植到Linux上吗?我的哀悼。请注意,、 等是“衰减”(由于缺乏正确术语)到其实际 C 类型(类型相当差)的类型定义。这些都是 Windows ism,因此您最终需要为端口编写类似的 typedef 或全部替换它们。LPCTSTRDWORD
0赞 sashang 7/19/2012
这是链接器错误,而不是编译器错误。用于尝试解决此问题的过程是遇到编译器错误时将使用的过程。所有错误告诉你的是,它找不到需要链接的静态库,换句话说,它找不到包含函数CWnd::create编译的文件。必须转到 Visual Studio 中的链接器设置对话框,并添加相关库。
0赞 Adam 7/19/2012
CWnd 是 MFC 的一部分。请确保链接 MFC。更熟悉最近 VS 的人可以告诉你如何做到这一点。
0赞 Alex Jansen 7/20/2012
如何确定哪个文件包含CWnd::create的编译?我一直在网络上查找,并且知道它属于 Microsoft 基础类库,但似乎找不到该库中实际文件的提及。MSDN 只是谈论。此外,一旦我确定了需要将链接器指向哪些文件,我应该具体在哪里执行此操作?它是否在项目属性->配置属性->库里纳->常规->其他库目录下?
0赞 Alex Jansen 7/20/2012
更新:我想这条路毕竟行不通。请看下面我对 Scotty 回答的回应。要么它仍在尝试从其他一些设置链接,要么 mfc90.dll 不是我需要链接到的文件。有什么想法吗?

答:

0赞 Scotty 7/19/2012 #1

链接器错误意味着它找到了标头,但找不到实现(obj 或 lib)。检查标头是否存在是没有意义的 - 您的代码已编译,因此编译器找到了标头。

看起来您需要链接到 MFC(即包含 CWnd 实现的库)。

在项目属性中,设置:

General > Use of MFC > Use MFC in a Shared DLL

至于 stdafx.h,它是一个预编译的头文件。您可以自己阅读这些内容。;)如果不需要它,可以在项目属性中将其关闭:

C/C++ > Precompiled Headers > Precompiled Header > Not Using Precompiled Headers

评论

0赞 Alex Jansen 7/20/2012
遗憾的是,该项目已设置为“在共享 DLL 中使用 MFC”。也许我链接到错误的 MFC 版本?我一直在看这个维基百科页面,它似乎列出了一堆不同的DLL。 我需要的CWnd函数是否包含在其中一个中?
0赞 Alex Jansen 7/20/2012
我继续搜索MFC90.dll,并在我的计算机上找到了11个具有不同文件大小的副本。其中 9 个位于 WinSxS 目录中,其中 4 个似乎用于不同版本的 x86 MFC 发行版。其中有几个不在维基百科列表中。不在 SxS 目录中的 2 个 MFC90.dll 文件位于 Visual Studio 目录本身中,其中一个似乎也适用于 x86。我应该如何判断要链接到哪一个?同样,一旦我找到正确的文件,我如何实际告诉IDE进行链接?对不起,所有的问题!
0赞 Alex Jansen 7/20/2012
Hmmm, so I tried adding the path to each of these MFC90.dll files to project properties->configuration properties->librarian->general->additional library directories. Each time the project successfully compiled (rather than simply saying it was up-to-date) but ran into the same linker errors. I decided to try one of the amd64 ones to see if it was actually compiling from the libraries I was specifying this way. However, that also succeeded, which tells me that it's not actually including this code. Again, how do I tell the IDE what to link to?
0赞 Alex Jansen 7/20/2012
Oh duh, DLL files are for linking at runtime, not from the IDE's linker. I guess that wasn't the file I was looking for anyway. Where would I find the correct .obj and/or .lib file(s)?
0赞 Scotty 7/20/2012
Correct, you link against libs, not DLLs. And don't worry about WinSxS, that doesn't matter to you. You could try two things: 1. Disable precompiled headers, and remove all #include <stdafx.h>. On rare occasions, I've seen very strange linker errors due to bugs(?) with precompiled headers. 2. Try linking against MFC statically, just to see what happens (this is a long shot). Set it to Use MFC in a Static Library.