VC6/VC2005均不支持行数超过65536的C/C++源代码文件
严格地,应该说,VC6或VC2005不能很好的支持对“行数超过65536的C/C++源代码文件”的跟踪调试。
这是我(liigo)在准备参予为易语言开发最新版的sqlite3支持库的时候偶然发现的。
从 SQLite 官方网站(sqlite.org)下载的 sqlite3 最新源代码整合版(amalgamation),其中 sqlite3.c 单个文件尺寸高达 3.3M,代码总行数接近 10 万行(98715行)。用 VC6 或 VC205 编译都没有问题,关键是对该文件的跟踪调试支持非常不好:我在调用 sqlite3_initialize() (定义在 sqlite3.c 中第 83992 行处)的代码处下断点,中断后单步跟踪进入(F11),发现VC调试器已经不能准定位源代码行号了,竟然中断在一堆反汇编后的二进制代码处;而直接到 sqlite3.c 中 sqlite3_initialize() 的函数体内下断点如何呢,根本下不了断点!根据VC助手(Visual Assist X)提示,函数 sqlite3_initialize() 定义在 sqlite3.c 的第 83992 行(正确),但执行跳转动作(F12 / Alt+G)后,光标却定位到 18456 行!而数值 18456 恰恰是数值 83992 被截断为两字节后的结果!
根据合理推论,我们初步猜测,在VC6/VC2005编译器生成的调试信息中,“行号”是用两字节的“unsigned short”(而非四字节的“unsigned int”)记录的。由此造成的结果是,一旦某个C/C++源代码文件总行数超过限制(65536行),就不能很好的跟踪调试文件中65536行以后的代码。
即使猜测属实,这也仅仅只是VC6/VC2005编译器的一个小小的设计疏忽,算不得什么。当年用一个字节存储日期中的年份、用四个字节存储IPv4,也都有过先例。问题是,谁能想到,竟然在人变态到,把一个C/C++源代码文件搞那么大肚子,接近10万行?!哈哈,这种事情还实实在在地发生在 sqlite3.c 身上,虽然该文件是由程序合并(amalgamate嘛)生成的。
问题既然出现了,先想办法解决吧。OK,发现 sqlite3.c 中有很多注释,把所有注释删除是不是会减少很多行?随手写了几行易语言代码,360毫秒内就把其中的注释全部删除:
(注意,上面代码中的正则表达式在 VC6 / VC2005 / EmEditor6 中均无效,因为它们不能很好的支持多行匹配模式(存疑)。)
经过以上易语言程序的处理,sqlite3.c 的代码行数减少了接近三万行,达到 71047 行,还是大于 65536。噫,又发现该文件中有很多连续的空行,把它们去掉试试?用正则表达式把“\n\n”替换为“\n”,代码行总缩减为 64476 行,OK,够了。
把瘦身后的 sqlite3.c 交给 VC6 / VC2005 编译调试,一切正常了。(瘦身后的 sqlite3_thin.c 可在此下载,经 Beyond Compare 2.2 对比核实,未发现非注释性代码被无辜删除,但无论如何不对结果做任何担保。)