【问题标题】:How do I follow this linker error?如何遵循此链接器错误?
【发布时间】:2012-07-18 02:52:24
【问题描述】:

我正在做我的第一份实习工作,仍在尝试在 Visual Studio 2008 上使用 get this horrible thing to compile。我已经花了一周时间研究 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。那里什么都没有,所以我查看了 VC++ 目录包含的 IDE 设置。第一个清单是: $(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 article 听起来像是在代码正常工作并且编译器以某种方式设法丢失 .obj 文件或 .lib 文件时发生此错误。我怎样才能让它再次指向正确的地方?

呃, -亚历克斯

【问题讨论】:

  • 你必须将这个怪物移植到Linux?节哀顺变。请注意,LPCTSTRDWORD 等是类型定义,它们“衰减”(因为缺少正确的术语)到它们的实际 C 类型(这是相当糟糕的类型)。这些都是 Windows 主义,因此您最终需要为您的端口编写类似的 typedef 或全部替换它们。
  • 这是一个链接器错误,而不是编译器错误。如果您遇到编译器错误,您用来尝试解决它的过程就是您要使用的过程。所有错误告诉你的是它找不到它需要链接的静态库,换句话说,它找不到包含函数 CWnd::create 的编译的文件。您必须转到 Visual Studio 中的链接器设置对话框并添加相关库。
  • CWnd 是 MFC 的一部分。确保您正在链接 MFC。更熟悉最近的 VS 的人可以告诉你如何做到这一点。
  • 如何确定哪个文件包含CWnd::create的编译?我一直在寻找整个网络,并且知道它属于 Microsoft 基础类库,但似乎在该库中找不到实际 files 的提及。 MSDN 只是谈论。此外,一旦我确定了需要将链接器指向的文件,我具体应该在哪里执行此操作?它会在项目属性->配置属性->图书馆员->通用->附加库目录下吗?
  • 更新:我想那条路径毕竟行不通。请参阅下面我对 Scotty 回答的回复。要么它仍在尝试从其他一些设置链接,要么 mfc90.dll 不是我需要链接到的文件。有什么想法吗?

标签: c++ visual-studio-2008 linker-errors unresolved-external lnk2001


【解决方案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

【讨论】:

  • 不幸的是,该项目已设置为在共享 DLL 中使用 MFC。也许我链接到了错误版本的 MFC?我一直在查看this Wikipedia 页面,该页面似乎列出了一堆不同的 DLL。我需要的 CWnd 函数是否包含在其中之一中?
  • 我继续搜索 MFC90.dll 并在我的计算机上找到了 11 个不同文件大小的副本。其中 9 个位于 WinSxS 目录中,其中 4 个似乎用于不同版本的 x86 MFC 发行版。其中一些不在维基百科列表中。不在 SxS 目录中的 2 个 MFC90.dll 文件位于 Visual Studio 目录本身中,其中一个似乎也适用于 x86。我应该如何判断要链接到哪一个?同样,一旦我找到正确的文件,我如何真正告诉 IDE 进行链接?抱歉所有问题!
  • 嗯,所以我尝试将每个 MFC90.dll 文件的路径添加到项目属性->配置属性->图书馆员->常规->其他库目录。每次项目成功编译(而不是简单地说它是最新的)但遇到相同的链接器错误。我决定尝试其中一个 amd64,看看它是否真的是从我指定的库中编译的。但是,这也成功了,这告诉我它实际上并未包含此代码。同样,我如何告诉 IDE 链接到什么?
  • 呵呵,DLL 文件用于在运行时进行链接,而不是来自 IDE 的链接器。我想那不是我一直在寻找的文件。我在哪里可以找到正确的 .obj 和/或 .lib 文件?
  • 正确,您链接的是库,而不是 DLL。不用担心 WinSxS,这对你来说并不重要。您可以尝试两件事: 1. 禁用预编译头文件,并删除所有#include 。在极少数情况下,由于带有预编译标头的错误(?),我看到了非常奇怪的链接器错误。 2.尝试静态链接MFC,看看会发生什么(这是一个很长的镜头)。将其设置为在静态库中使用 MFC。
猜你喜欢
  • 2014-01-10
  • 2020-02-11
  • 2010-09-10
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
  • 2011-08-08
  • 1970-01-01
相关资源
最近更新 更多