构建发布 编译的常见错误

liuxue.gu@hotmail.com · 2011年09月19日 · 3 次阅读

VC++ 编译的常见错误

1、fatal error C1010: unexpected end of file while looking for precompiled header directive。 寻找预编译头文件路径时遇到了不该遇到的文件尾。(一般是没有 #include "stdafx.h")

2、fatal error C1083: Cannot open include file: 'R…….h': No such file or directory 不能打开包含文件 “R…….h”:没有这样的文件或目录。

3、error C2011: 'C……': 'class' type redefinition 类 “C……” 重定义。

4、error C2018: unknown character '0xa3' 不认识的字符'0xa3'。(一般是汉字或中文标点符号)

5、error C2057: expected constant expression 希望是常量表达式。(一般出现在 switch 语句的 case 分支中)

6、error C2065: 'IDD_MYDIALOG' : undeclared identifier “IDD_MYDIALOG”:未声明过的标识符。

7、error C2082: redefinition of formal parameter 'bReset' 函数参数 “bReset” 在函数体中重定义。

8、error C2143: syntax error: missing ':' before '{' 句法错误:“{” 前缺少 “;”。

9、error C2146: syntax error : missing ';' before identifier 'dc' 句法错误:在 “dc” 前丢了 “;”。

10、error C2196: case value '69' already used 值 69 已经用过。(一般出现在 switch 语句的 case 分支中)

11、error C2509: 'OnTimer' : member function not declared in 'CHelloView' 成员函数 “OnTimer” 没有在 “CHelloView” 中声明。

12、error C2511: 'reset': overloaded member function 'void (int)' not found in 'B' 重载的函数 “void reset(int)” 在类 “B” 中找不到。

13、error C2555: 'B::f1': overriding virtual function differs from 'A::f1' only by return type or calling convention 类 B 对类 A 中同名函数 f1 的重载仅根据返回值或调用约定上的区别。

14、error C2660: 'SetTimer' : function does not take 2 parameters “SetTimer” 函数不传递 2 个参数。

15、warning C4035: 'f……': no return value “f……” 的 return 语句没有返回值。

16、warning C4553: '= =' : operator has no effect; did you intend '='? 没有效果的运算符 “= =”;是否改为 “=”?

17、warning C4700: local variable 'bReset' used without having been initialized 局部变量 “bReset” 没有初始化就使用。

18、error C4716: 'CMyApp::InitInstance' : must return a value “CMyApp::InitInstance” 函数必须返回一个值。

19、LINK : fatal error LNK1168: cannot open Debug/P1.exe for writing 连接错误:不能打开 P1.exe 文件,以改写内容。(一般是 P1.Exe 还在运行,未关闭)

20、error LNK2001: unresolved external symbol "public: virtual _ _thiscall C……::~C……(void)" 连接时发现没有实现的外部符号(变量、函数等)

[align=center][align=center][font=SimSun][size=14.0pt] VC6.0 编译常见错误 [/font] [/align][/align][font=SimSun] [/font] [font=SimSun] [/font] [font=SimSun] 第一部分 编译错误 [/font]

[font=SimSun] 1. error C2001: newline in constant[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2001[/font]

[font=SimSun] 直译:在常量中出现了换行。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun]([/font][font=SimSun] 1)

字符串常量、字符常量中是否有换行。[/font]

[font=SimSun]([/font][font=SimSun] 2) 在这句语句中,某个字符串常量的尾部是否漏掉了双引号。[/font]

[font=SimSun]([/font][font=SimSun] 3) 在这语句中,某个字符创常量中是否出现了双引号字符 “"”,但是没有使用转义符 “\"”。[/font]

[font=SimSun]([/font][font=SimSun] 4) 在这句语句中,某个字符常量的尾部是否漏掉了单引号。[/font]

[font=SimSun]([/font][font=SimSun] 5) 是否在某句语句的尾部,或语句的中间误输入了一个单引号或双引号。[/font]

[font=SimSun] [/font]

[font=SimSun] 2. error C2015: too many charactersin constant[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2015[/font]

[font=SimSun] 直译:字符常量中的字符太多了。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 单引号表示字符型常量。一般的,单引号中必须有,也只能有一个字符(使用转义符时,转义符所表示的字符当作一个字符看待),如果单引号中的字符数多于 [/font][font=SimSun] 4 个,就会引发这个错误。[/font]

[font=SimSun] 另外,如果语句中某个字符常量缺少右边的单引号,也会引发这个错误,例如:[/font]

[font=SimSun] if (x == 'x || x == 'y') { … }[/font]

[font=SimSun] 值得注意的是,如果单引号中的字符数是 [/font][font=SimSun] 2-4 个,编译不报错,输出结果是这几个字母的 ASC 码作为一个整数(int,4B)整体看待的数字。[/font]

[font=SimSun] 两个单引号之间不加任何内容会引发如下错误:[/font][font=SimSun] errorC2137: empty character constant。[/font]

[font=SimSun] [/font]

[font=SimSun] 3. error C2018: unknown character'0x##'[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2018[/font]

[font=SimSun] 直译:未知字符 ‘[/font][font=SimSun] 0x##’。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 0x## 是字符 ASC 码的 16 进制表示法。这里说的未知字符,通常是指全角符号、字母、数字,或者直接输入了汉字。如果全角字符和汉字用双引号包含起来,则成为字符串常量的一部分,是不会引发这个错误的。[/font]

[font=SimSun] [/font]

[font=SimSun] 4. error C2041: illegal digit '#'for base '8'[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2141[/font]

[font=SimSun] 直译:在八进制中出现了非法的数字 ‘[/font][font=SimSun]#’(这个数字 # 通常是 8 或者 9)。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 如果某个数字常量以 “[/font][font=SimSun] 0” 开头(单纯的数字 0 除外),那么编译器会认为这是一个 8 进制数字。例如:“089”、“078”、“093” 都是非法的,而 “071” 是合法的,等同于是进制中的 “57”。[/font]

[font=SimSun] [/font]

[font=SimSun] 5. error C2065: 'xxxx' : undeclaredidentifier[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2065[/font]

[font=SimSun] 直译:标识符 “[/font][font=SimSun] xxxx” 未定义。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 首先,解释一下什么是标识符。标志符是程序中出现的除关键字之外的词,通常由字母、数字和下划线组成,不能以数字开头,不能与关键字重复,并且区分大小写。变量名、函数名、类名、常量名等等,都是标志符。所有的标志符都必须先定义,后使用。标志符有很多种用途,所以错误也有很多种原因。[/font]

[font=SimSun]([/font][font=SimSun] 1) 如果 “xxxx” 是一个变量名,那么通常是程序员忘记了定义这个变量,或者拼写错误、大小写错误所引起的,所以,首先检查变量名是否正确。(关联:变量,变量定义)[/font]

[font=SimSun]([/font][font=SimSun] 2) 如果 “xxxx” 是一个函数名,那就怀疑函数名是否没有定义。可能是拼写错误或大小写错误,当然,也有可能是你所调用的函数根本不存在。还有一种可能,你写的函数在你调用所在的函数之后,而你有没有在调用之前对函数原形进行申明。(关联:函数申明与定义,函数原型)[/font]

[font=SimSun]([/font][font=SimSun] 3) 如果 “xxxx” 是一个库函数的函数名,比如 “sqrt”、“fabs”,那么看看你在 cpp 文件已开始是否包含了这些库函数所在的头文件(.h 文件)。例如,使用 “sqrt” 函数需要头文件 math.h。如果 “xxxx” 就是 “cin” 或 “cout”,那么一般是没有包含 “iostream.h”。(关联:#include,cin,cout)[/font]

[font=SimSun]([/font][font=SimSun] 4) 如果 “xxxx” 是一个类名,那么表示这个类没有定义,可能性依然是:根本没有定义这个类,或者拼写错误,或者大小写错误,或者缺少头文件,或者类的使用在申明之前。(关联:类,类定义)[/font]

[font=SimSun]([/font][font=SimSun] 5) 标志符遵循先申明后使用原则。所以,无论是变量、函数名、类名,都必须先定义,后使用。如使用在前,申明在后,就会引发这个错误。[/font]

[font=SimSun]([/font][font=SimSun] 6) C++ 的作用域也会成为引发这个错误的陷阱。在花括号之内变量,是不能在这个花括号之外使用的。类、函数、if、do(while)、for 所引起的花括号都遵循这个规则。(关联:作用域)[/font]

[font=SimSun]([/font][font=SimSun] 7) 前面某句语句的错误也可能导致编译器误认为这一句有错。如果你前面的变量定义语句有错误,编译器在后面的编译中会认为该变量从来没有定义过,以致后面所有使用这个变量的语句都报这个错误。如果函数申明语句有错误,那么将会引发同样的问题。[/font]

[font=SimSun] [/font]

[font=SimSun] 6. error C2086: 'xxxx' :redefinition[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2374[/font]

[font=SimSun] 直译:“[/font][font=SimSun] xxxx” 重复申明。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 变量 “[/font][font=SimSun] xxxx” 在同一作用域中定义了多次。检查 “xxxx” 的每一次定义,只保留一个,或者更改变量名。[/font]

[font=SimSun] [/font]

[font=SimSun] 7. error C2374: 'xxxx' :redefinition; multiple initialization[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2374[/font]

[font=SimSun] 直译:“[/font][font=SimSun] xxxx” 重复申明,多次初始化。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 变量 “[/font][font=SimSun] xxxx” 在同一作用域中定义了多次,并且进行了多次初始化。检查 “xxxx” 的每一次定义,只保留一个,或者更改变量名。[/font]

[font=SimSun] [/font]

[font=SimSun] 8. C2143: syntax error : missing';' before (identifier) 'xxxx'[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2143[/font]

[font=SimSun] 直译:在(标志符)“[/font][font=SimSun] xxxx” 前缺少分号。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 这是 [/font][font=SimSun] VC6 的编译期最常见的误报,当出现这个错误时,往往所指的语句并没有错误,而是它的上一句语句发生了错误。其实,更合适的做法是编译器报告在上一句语句的尾部缺少分号。上一句语句的很多种错误都会导致编译器报出这个错误:[/font]

[font=SimSun]([/font][font=SimSun] 1) 上一句语句的末尾真的缺少分号。那么补上就可以了。[/font]

[font=SimSun]([/font][font=SimSun] 2) 上一句语句不完整,或者有明显的语法错误,或者根本不能算上一句语句(有时候是无意中按到键盘所致)。[/font]

[font=SimSun]([/font][font=SimSun] 3) 如果发现发生错误的语句是 cpp 文件的第一行语句,在本文件中检查没有错误,而且这个文件使用双引号包含了某个头文件,那么检查这个头文件,在这个头文件的尾部可能有错误。[/font]

[font=SimSun] [/font]

[font=SimSun] 9. error C2137: empty characterconstant[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2137[/font]

[font=SimSun] 直译:空的字符定义。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 原因是连用了两个单引号,而中间没有任何字符。一般的,单引号表示字符型常量,单引号中必须有,也只能有一个字符(使用转义符时,转义符所表示的字符当作一个字符看待)。两个单引号之间不加任何内容是不允许的。[/font]

[font=SimSun] 需要注意的是:如果单引号中的字符数是 [/font][font=SimSun] 2-4 个,编译不报错,输出结果是这几个字母的 ASC 码作为一个整数(int,4B)整体看待的数字。[/font]

[font=SimSun] 如果单引号中的字符数多于 [/font][font=SimSun] 4 个,会引发 2015 错误:error C2015: too manycharacters in constant。[/font]

[font=SimSun] [/font]

[font=SimSun] 10. error C2374: 'xxxx' :redefinition; multiple initialization[/font]

[font=SimSun] 编号:[/font][font=SimSun] C2374[/font]

[font=SimSun] 直译:“[/font][font=SimSun] xxxx” 重复申明,多次初始化。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 变量 “[/font][font=SimSun] xxxx” 在同一作用域中定义了多次,并且进行了多次初始化。检查 “xxxx” 的每一次定义,只保留一个,或者更改变量名。[/font] [font=SimSun] [/font]

[font=SimSun] 第二部分链接错误 [/font]

[font=SimSun] 1. error LNK2001: unresolvedexternal symbol _main[/font]

[font=SimSun] 编号:[/font][font=SimSun] LNK2001[/font]

[font=SimSun] 直译:未解决的外部符号:[/font][font=SimSun]_main。[/font]

[font=SimSun] 错误分析:缺少 [/font][font=SimSun] main 函数。看看 main 的拼写或大小写是否正确。[/font]

[font=SimSun] [/font]

[font=SimSun] 2. error LNK2005: _main alreadydefined in xxxx.obj[/font]

[font=SimSun] 编号:[/font][font=SimSun] LNK2005[/font]

[font=SimSun] 直译:[/font][font=SimSun]_main 已经存在于 xxxx.obj 中了。[/font]

[font=SimSun] 错误分析:[/font]

[font=SimSun] 直接的原因是该程序中有多个(不止一个)[/font][font=SimSun] main 函数。这是初学 C++ 的低年级同学在初次编程时经常犯的错误。这个错误通常不是你在同一个文件中包含有两个 main 函数,而是在一个 project(项目)中包含了多个 cpp 文件,而每个 cpp 文件中都有一个 main 函数。引发这个错误的过程一般是这样的:你写完成了一个 C++ 程序的调试,接着你准备写第二个 C++ 文件,于是你可能通过右上角的关闭按钮关闭了当前的 cpp 文件字窗口(或者没有关闭,这一操作不影响最后的结果),然后通过菜单或工具栏创建了一个新的 cpp 文件,在这个新窗口中,程序编写完成,编译,然后就发生了以上的错误。原因是这样的:你在创建第二个 cpp 文件时,没有关闭原来的项目,所以你无意中新的 cpp 文件加入你上一个程序所在的项目。切换到 “FileView” 视图,展开 “Source Files” 节点,你就会发现有两个文件。[/font]

[font=SimSun] 在编写 [/font][font=SimSun] C++ 程序时,一定要理解什么是 Workspace、什么是 Project。每一个程序都是一个 Project(项目),一个 Project 可以编译为一个应用程序(.exe),或者一个动态链接库(.dll)。通常,每个 Project 下面可以包含多个.cpp 文件,.h 文件,以及其他资源文件。在这些文件中,只能有一个 main 函数。初学者在写简单程序时,一个 Project 中往往只会有一个 cpp 文件。Workspace(工作区)是 Project 的集合。在调试复杂的程序时,一个 Workspace 可能包含多个 Project,但对于初学者的简单的程序,一个 Workspace 往往只包含一个 Project。[/font]

[font=SimSun] 当完成一个程序以后,写另一个程序之前,一定要在 “[/font][font=SimSun] File” 菜单中选择 “Close Workspace” 项,已完全关闭前一个项目,才能进行下一个项目。避免这个错误的另一个方法是每次写完一个 C++ 程序,都把 VC6 彻底关掉,然后重写打开 VC6,写下一个程序。[/font] [font=SimSun] [/font]

[[i] 本帖最后由 scmroad 于 2011-9-19 15:30 编辑 ]

1、问题阐述

Link(连接) 错误时常见的错误,其中又以 Link2001 最为常见,引起 Link2001 错误的原因是什么呢?

2、Link2001 错误原因及实现技巧

(1)由于编码错误导致的 Link2001 错误

①不相匹配的程序代码或模块定义(.DEF)文件导致 Link2001。例如,如果在 C++ 源文件内声明了一变量 “var1”,视图却在另一个文件内以变量 “var1” 访问该变量。

②如果使用的内联函数是在.cpp 文件内定义的,而不是在头文件内定义将导致 Link2001 错误

③调用函数如果所用的参数类型头函数与声明时的类型不符将会产生 Link2001 错误

④视图从基类的构造函数或析构函数中调用虚拟函数时将会导致 Link2001 错误

⑤要注意函数和变量的可公用性,只有全局变量、函数是可共用的。静态函数和静态变量具有相同的使用范围。当试图从文件外部调用任何没有在该文件内声明的静态变量时将导致编译错误或 Link2001 错误。

(2)由于编译和联机的设置而造成的 Link2001 错误

①如果编译时使用的是/NOD(/NODERAULTLIB) 选项,程序所需要的运行库和 MFC 将由编译器写入目标文件模块,但除非在文件中明确包含这些库名,否则这些库不会被链接进工程文件。这种情况下使用/NOD 将导致 Link2001 错误。

②如果没有为 WinMainCRTStartup 设定程序入口,在使用 Unicode 和 MFC 时将得到 “unresolved external on WinMain@16“的 Link2001 错误信息。

③使用/MD 选项编译时,既然所有的运行库都被保留在动态链接库之内,如果源文件中对 “func” 的引用,在目标文件里即对 “impfunc” 的引用。如果试图使用静态库 LIBC.lib 或 LIBCMT.lib 进行链接,将在impfunc 上发生 Link2001 错误。如果不使用/MD 选项编译,在使用 MSVCxx.lib 链接时也会发生 Link2001 错误。

④在使用/ML 编译时,如用 LIBCMT.lib 链接会在_errno 上发生 Link2001 错误。

⑤当编译调试版的应用程序时,如果采用发行版模态库进行链接也会产生 Link2001 错误;同样,使用调试版模态库链接发行版应用程序时也会产生相同的错误。

⑥不同版本的库和编译器的混合使用也能产生问题,因为新库的库里可能包含早先的版本没有的符号和说明。

⑦在不同的模块中使用内联和非内联的编译选项能够导致 Link2001 错误。如果创建 C++ 库时打开了函数内联(/Ob2 或/Ob2),但是在描述该函数的相应头文件却关闭了函数内联(没有 inline 关键字),将得到错误信息。为避免该问题的发生,应该在相应的头文件中用 inline 关键字标志位内联函数。

想要获得更多内容,可点击:《Visual C++ 代码参考与技巧大全》学习笔记——索引随笔

需要 登录 后方可回复。