记一次 pugixml 编译错误的解决
原总结工具editpadvs编译错误file locator
缘起
前一阵子,平台在换基线,底层接口变了很多,因此引出了至少 20000
pugixml-compile-error
诡异吧?标准模板库里(参考 vector
的实现)大量使用了这种技法( c++
中典型的 placement new
)。为什么这里就不行了呢?
杀手锏
解决这种诡异的编译错误,杀手锏是查看预编译生成的文件。好在 vs
vs-preprocess-option
/P
表示将预处理的输出写入到文件中(每个 .cpp
文件会生成一个对应的 .i
/C
可以在有问题的源码上方加上独特的标记 // TODO:BCN check here
,这样可以通过搜索快速定位到错误的代码的位置。强烈建议这么做,因为预处理输出的文件实在是太大了。
查看输出结果
在 vs
中按上图所示设置好,然后重新编译,编译完成后会生成如下几个 .i
generated-preprocessed-files
注意: 相对于 .cpp 文件,.i 文件非常巨大。在这个简单的示例工程中,即使没写什么业务代码,生成出来的文件都有 11 MB 多,实际项目中产生的 .i
大多数情况下,可以很明确的知道要查看哪个 .i
文件(可以通过错误提示来判断)。但是本例比较特殊,不知道应该查看哪个 .i
文件(报错的文件是 pugixml.cpp
,但是生成的 .i
文件中并没有名为 pugixml.i
请出 File Locator
,设置搜索目录为 .i
文件所在的目录,设置文件名为 *.i
,并设置 Containing text
为 "// TODO:BCN check here"
,点击 Start
search-mark-using-file-locator
很快就得到了搜索结果 —— 文件 PugiXmlCompileErrorDlg.i
的第 664200
使用 EditPad
打开 PugiXmlCompileErrorDlg.i
,按 Ctrl + g
,在弹出的界面中的行号位置输入 664200
即可跳转过去。但是 EditPad
中的行号和 File Locator
给出来的行号不匹配,664200
行并不是期待的注释内容。没关系,按 ctrl + f
重新搜索一遍,瞬间就搜到了(感叹一下 EditPad
view-preprocessed-file-content-in-editpad
注意看高亮内容,本来应该是 new (memory) xml_attribute_struct(page);
的,但是却在 new
和 (memory)
恍然大悟
看到这,我瞬间就明白是怎么回事了,相信有 MFC
在 DEBUG
版的 MFC
程序中,new
可能会被定义成 DEBUG_NEW
:
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
而 DEBUG_NEW
// VC\atlmfc\include\afx.h
#define DEBUG_NEW new(THIS_FILE, __LINE__)
所以,new
最终被替换成了 new(THIS_FILE, __LINE__)
虽然找到了原因,但是还有一些细节没有弄清楚。
深入思考
- 为什么标准模板库中可以这么用?在
pugixml
- 为什么这个编译错误报在
pugixml.cpp
- 中?明明工程中并没有添加
pugixml.cpp
因为这两个问题都比较简单,本文不打算深入探讨,直接给出结论。
**问题1:**标准库可以这么用是因为 —— 在包含标准库中的头文件时,new
还是 new
,没有被定义成 DEBUG_NEW
。而 pugixml
有问题,是因为在包含 pugixml.hpp
之前,new
被定义成了 DEBUG_NEW
。如下图:
compare-include
说明: 实际项目远比示例代码要复杂。不是那么容易能看出来的。
**问题2:**因为如果定义了 PUGIXML_HEADER_ONLY
并且没有定义 PUGIXML_SOURCE
, pugixml.hpp
会在内部包含 pugixml.cpp
。
include-pugixml_cpp_in_hpp_file
是的,你没看错,源文件也是可以通过 #include
解决
只需要把 #include "pugixml/pugixml.hpp"
移动到 #ifdef _DEBUG
上方即可。或者干脆注释掉 #define new DEBUG_NEW
总结
- 虽然之前解决过类似的问题,但是在耗费大量体力和脑力之后,很难保持清醒的头脑。
EditPad
- 在
vs
- 中,可以通过
/P
- 编译选项来输出预编译的结果到文件中(
.i
- 并不是只有
.h
- 文件才能被
include
- ,
.cpp
- 文件也可以被
include
- 。
考考你
什么情况下可以 #include xxx.cpp
,什么情况下不能呢?为什么?
欢迎留言讨论交流。
参考资料
https://en.cppreference.com/w/cpp/language/new
https://en.wikipedia.org/wiki/Placement_syntax
欢迎各位小伙伴指出不足,提出建议!感谢关注我的博客:)
作 者:编程难
码云博客:https://bianchengnan.gitee.io
github博客:https://bianchengnan.github.io
版权所有,转载请保留原文链接:)