Part.I Introduction
本文致力于记录笔者在使用 C++ 过程中遇到的一些问题以及相应的解决方案。
Part.II C++ 编译问题
一句话就可说明的问题:
C2572
重定义默认参数,函数中参数的默认值能且只能赋值一次,一般在函数声明中赋值。LNK2001
引用第三方库时没有进行依赖项配置 『解』方法有两种:-
- ① CMakeList.txt 中加入
target_link_libraries(${PROJECT_NAME} xx)
- ① CMakeList.txt 中加入
-
- ② 选中项目→右键『属性』→『链接器』→『输入』→『附加依赖项』→添加依赖库的名字(
*.lib
,用空格或分号间隔多项)
- ② 选中项目→右键『属性』→『链接器』→『输入』→『附加依赖项』→添加依赖库的名字(
- 添加全局包含目录和库目录:视图→其他窗口→属性管理器→随便选择一个项目→
RelWithDebInfo | x64
(具体看自己的项目)→Microsoft.Cpp.x64.user
→双击打开→VC++目录→添加包含目录和库目录
Chap.I 换行符问题
众所周知,在 Windows 系统下的换行符是CRLF
,但是在 Linux 系统下的换行符是LF
,在跨平台编写C++程序时经常会遇到这种问题。在2022-07-28
笔者遇到了这个问题,当初没有意识到,搞得我心态爆炸。睡了个午觉醒来后突然意识到会不会是这个问题。它给我报的错一大堆,比如有:
- 错误 C2447 “{”: 缺少函数标题(是否是老式的形式表?)
- 错误 C2065 “end_ap”: 未声明的标识符
- 错误 C2046 非法的 case
- 错误 C2143 语法错误: 缺少“;”(在“{”的前面)
- 错误 C4430 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
解决方案也很简单,只需将报错的文件的换行符换一下就行,一般都在屏幕右下角.
ps:如果直接在windows平台和Linux 平台传文件的话,文件的换行符是不会发生改变的;当使用git的时候,文件的换行符会自动转换为其所在平台支持的换行符(至少Linux系统是这样的)
Chap.II LNK2019 无法解析的外部符号
有时候在编译的过程中可能会报错:『LNK2019 无法解析的外部符号』。报这个错误的原因一般有如下几种
- 在使用动态库时候,没有包含相应的lib。『解』
#pragma comment( lib,"xxxx.lib");
- 函数只进行了声明而没有进行定义。『解』为声明的函数添加函数实现。
- 缺少
.obj
目标文件。『解』重新设置文件编译的路径,重新编译。 - 有时候的错误是下报的,把 build 文件夹删掉,重新
cmake→build
即可!
Chap.III LNK2001 无法解析的外部符号
可以试试将解决方案平台改为x64
。
Chap.IV 提高 C++ 的编译速度
主要有如下一些措施
- 声明与实现分离,删除不必要的
#include
- 预编译头文件(PCH):把一些常用但不常改动的头文件放在预编译头文件中。这样,至少在单个工程中你不需要在每个编译单元里一遍又一遍的load与解析同一个头文件了。
- 减少文件数量,把多个CPP合到一起(在不会造成不便的情况下)
- 非必须不要将
#include
放进*.h
文件,而是放在*.cpp
文件。
Chap.V LNK1104: 无法打开文件“xxxrd.lib”
出现这一错误的原因可能有:
- 没有包含相应的 lib(附加依赖项,cmake
target_link_libraries
) - 没有生成相应的 lib:检查为什么没有生成 lib,可能没有
__declspec(dllexport)
,一般要#define Libxxx_LIBRARY_EXPORT __declspec(dllexport)
,然后在头文件类或类外函数的前面加上Libxxx_LIBRARY_EXPORT
修饰。
参考博文:lib 和 dll 的区别、生成以及使用详解 | windows中静态库lib和动态dll的区别及使用方法
Part.III 程序运行问题
Chap.I 不同平台变量默认赋值不同
在2022-07-28
这天,我发现同一套程序,同样的配置,在不同平台运行的结果差别很大。出现这样的原因可能有以下几种
- 不同平台对未赋值变量的默认赋值不同,比如对于bool类型的变量,在Linux系统下的默认值是
false
,但是在windows下的默认值可能就是true
。 - 处于内存占用的考量,不同级别平台对数据类型的默认精度(位数)可能不同,但是影响估计不是很大。
- 还有一些其他可能的原因,暂未知。
规避的方法就是:函数和类里面的变量,声明的时候都给个初值。不管了 bool, int 还是 double
Chap.II xx处有未经处理的异常: 0xC0000005: xx
只要是和内存相关的基本都是有可能的。
Chap.III C4996 scanf 等不安全
mkdir / fopen / strcpy / stricmp / scanf / sprintf /…
比如可能会报错
'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead
或者
'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
解决方案一般有如下几种:
1、在预处理器中加入_CRT_SECURE_NO_WARNINGS
:项目右键→属性→C/C++→预处理器定义→加入即可
2、在 include 前面加上 #define _CRT_SECURE_NO_WARNINGS
3、使用它提示的:mkdir
改写为 _mkdir
;fopen
改写为 fopen_s
;stricmp
改写为 stricmp_s
;strcpy
改写为 strcpy_s
;scanf
改写为 scanf_s
; sprintf
改写为 sprintf_s
等等。
Chap.IV Linux 运行下找不到动态库 *.so
修改 ~/.bashrc
文件
sudo vi ~/.bashrc
在里面加入:
export LD_LIBRARY_PATH=/xxxx/xxxx/lib:$LD_LIBRARY_PATH
# /xxxx/xxxx/lib 是你动态库的路径
保存关闭 vim 编辑器,然后
source ~/.bashrc
完事!
Part.IV CMake 遇到的问题
Chap.I 一句话问题
下面是遇到的简单的问题
- 文件夹在 cmake 的时候没有加进去:文件夹是空的,所以只需 在空文件夹中加几个文件 就可以了。
- 对一个编译好的程序,又进行了源码的修改,遇到问题:
CMake Error: The source directory ““ does not exist. Specify --help for usage
。解决方案:删除build
文件夹中的CMakeCache.txt
文件,重新cmake, make
- Linux 平台下 cmake 命令找不到
cmake: command not found
:原因可能是:①未安装 cmake;②没有加环境变量。解决方法:下载安装 cmake,在.bash_profile
中加入环境变量即可。