首页 > 其他分享 >记一次 pugixml 编译错误的解决

记一次 pugixml 编译错误的解决

时间:2022-12-13 11:02:28浏览次数:67  
标签:文件 错误 pugixml 编译 cpp new include DEBUG

记一次 pugixml 编译错误的解决

原总结工具editpadvs编译错误file locator

缘起

前一阵子,平台在换基线,底层接口变了很多,因此引出了至少 ​​20000​

记一次 pugixml 编译错误的解决_编译错误

pugixml-compile-error

诡异吧?标准模板库里(参考 ​​vector​​ 的实现)大量使用了这种技法( ​​c++​​ 中典型的 ​​placement new​​)。为什么这里就不行了呢?

杀手锏

解决这种诡异的编译错误,杀手锏是查看预编译生成的文件。好在 ​​vs​

记一次 pugixml 编译错误的解决_编译错误_02

vs-preprocess-option

​/P​​ 表示将预处理的输出写入到文件中(每个 ​​.cpp​​ 文件会生成一个对应的 ​​.i​​​​/C​​可以在有问题的源码上方加上独特的标记 ​​// TODO:BCN check here​​,这样可以通过搜索快速定位到错误的代码的位置。强烈建议这么做,因为预处理输出的文件实在是太大了。

查看输出结果

在 ​​vs​​ 中按上图所示设置好,然后重新编译,编译完成后会生成如下几个 ​​.i​

记一次 pugixml 编译错误的解决_xml_03

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​

记一次 pugixml 编译错误的解决_搜索_04

search-mark-using-file-locator

很快就得到了搜索结果 —— 文件 ​​PugiXmlCompileErrorDlg.i​​ 的第 ​​664200​​使用 ​​EditPad​​ 打开 ​​PugiXmlCompileErrorDlg.i​​,按 ​​Ctrl + g​​ ,在弹出的界面中的行号位置输入 ​​664200​​ 即可跳转过去。但是 ​​EditPad​​ 中的行号和 ​​File Locator​​ 给出来的行号不匹配,​​664200​​ 行并不是期待的注释内容。没关系,按 ​​ctrl + f​​ 重新搜索一遍,瞬间就搜到了(感叹一下 ​​EditPad​

记一次 pugixml 编译错误的解决_搜索_05

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__)​

虽然找到了原因,但是还有一些细节没有弄清楚。

深入思考

  1. 为什么标准模板库中可以这么用?在

​pugixml​

  1. 为什么这个编译错误报在

​pugixml.cpp​

  1. 中?明明工程中并没有添加

​pugixml.cpp​

因为这两个问题都比较简单,本文不打算深入探讨,直接给出结论。

**问题1:**标准库可以这么用是因为 —— 在包含标准库中的头文件时,​​new​​ 还是 ​​new​​,没有被定义成 ​​DEBUG_NEW​​。而 ​​pugixml​​ 有问题,是因为在包含 ​​pugixml.hpp​​ 之前,​​new​​ 被定义成了 ​​DEBUG_NEW​​。如下图:

记一次 pugixml 编译错误的解决_搜索_06

compare-include

说明: 实际项目远比示例代码要复杂。不是那么容易能看出来的。

**问题2:**因为如果定义了 ​​PUGIXML_HEADER_ONLY​​ 并且没有定义 ​​PUGIXML_SOURCE​​, ​​pugixml.hpp​​ 会在内部包含 ​​pugixml.cpp​​。

记一次 pugixml 编译错误的解决_编译错误_07

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://www.enseignement.polytechnique.fr/informatique/INF478/docs/Cpp/en/cpp/memory/new/operator_new.html​

欢迎各位小伙伴指出不足,提出建议!感谢关注我的博客:)

作 者:​​编程难​​

码云博客:​​https://bianchengnan.gitee.io​

github博客:​​https://bianchengnan.github.io​

版权所有,转载请保留原文链接:)



标签:文件,错误,pugixml,编译,cpp,new,include,DEBUG
From: https://blog.51cto.com/u_15469822/5933155

相关文章