通过C / C ++和编译器错误/限制进行编译

时间:2013-05-08 19:02:42

标签: c++ c compiler-construction language-implementation

我正在研究通过C编译实现高级(类似Lisp)语言的可能性(或者如果异常变得足够有用,可能是C ++);这是许多项目以前使用过的策略。当然,这会生成C代码,而不是在某些方面超出你手工编写的任何复杂程度。

现代C编译器在正常使用中非常可靠,但很难知道在异常压力下边缘情况下潜伏的错误,特别是如果你过一些“没有程序员会写一个大于Y的X”隐藏限制。

在我看来,这些事实的巧合可能会导致不快乐。

在主要编译器的合理最新版本(例如GCC,Microsoft C ++,Clang)中,是否有任何已知的情况,或者是否有一种很好的方法来查找生成的代码绊倒边缘案例错误/限制?

4 个答案:

答案 0 :(得分:1)

简答:

如果您需要编译器的性能而不是解释器(或预编译器+解释器)的易用性,您别无选择。你将编译成一些较低级别的语言,而C语言是今天的汇编语言,C ++就像C一样可用,也适合C这个任务。没有理由你应该担心这条路线。从某种意义上说,它实际上是一条非常常见的路线。

答案很长:

生成的代码绝不是不寻常的。即使相对适度使用生成的代码,也会导致C源“与任何程序员编写的不同”,数量(重复数百万次的小变量)或质量(语言特征的组合)人类永远不会使用,但仍然是合法的C ++)。还有相当多的编译器可以编译成C或C ++,some famous并且为编写C和C ++语言标准的人所熟知。

最常见的C和C ++编译器可以很好地处理生成的代码。是的,它们永远不会完美。

  • 编译器可能有各种简单的限制,例如最大代码行 长度;一旦遇到这些产品,这些产品往往会被记录在案并且易于遵守。
  • 编译器可能存在缺陷。
    • 对于生成的代码而言,某些类型的缺陷实际上不像手写代码那样 。一旦你开始理解模式并关心问题,你的代码生成器实际上给你一定程度的自由来系统地处理许多情况。
    • 如果有足够的编译器用户,很快就会发现导致编译器无法正确编译有效代码的缺陷。它们被编译器供应商视为特别​​高优先级的缺陷。即使编译器本质上已经死亡或服务于利基市场,因此没有可用的修复,互联网上往往会提供大量信息,包括人们现有的解决缺陷的经验(不同的编译器,不同的代码构造,不同的编译器)交换机...解决方案变化很大,可能会觉得很尴尬,但没有人因为某些软件有问题而放弃工作,对吧?因此,通常可以选择可搜索的解决方案。

通常很好地致力于跨编译器的可移植性,但也了解并跟踪可移植性的限制。如果您没有很好地测试特定的C或C ++编译器,请不要声称它可以作为工具集的一部分。

你在问C和C ++之间的隐含问题。嗯,这里有更多的灰色阴影。 C ++是一种非常丰富的语言。您可以在生成器中使用几乎所有C ++功能以达到良好的目的,但在某些情况下,您应该问自己一个特定的主要功能是否会成为一种负担,使您付出的代价超过它带给您的成本。例如,不同的编译器使用不同的策略进行模板实例化。隐式实例化可能导致可移植生成代码无法预料的复杂性。如果模板可以帮助您极大地设计发生器,请不要犹豫,使用它们;但如果你只有一个边缘用例,请记住,你有比大多数人更好的理由限制你生成的语言。

答案 1 :(得分:1)

这可能不是您正在寻找的答案,但几年前,我参与了一个项目,其中系统的某些部分是用更高级别的语言编写的,在那里很容易构建状态机流程。这种语言产生了随后编译的C代码。我们在这个项目中使用的编译器是gcc(版本大约2.95 - 不要引用我,但肯定是3.0之前的版本)。我们遇到了几个代码生成错误,但是,从我的记忆中更多的是使用一个不那么受欢迎的处理器[揭示哪个处理器可能揭示我不应该关于项目的东西,所以我宁愿不说它是什么,即使它是很久以前的]。

一位接近我的同事正在调查其中一个代码生成错误,它的功能大约为200k行,所有功能都是一个很大的switch语句,每个case都在switch语句中大约50-1000行每个(在其中有几层子开关语句)。

从我的记忆中,代码崩溃了,因为它产生了一个无效的操作或者存储在已经被其他东西占用的寄存器中的东西,所以一旦你找到正确的代码,它就会因为非法的内存访问而失败 - 它与代码的长度无关,因为我的同事最终设法将其降低到大约30行代码(经过大量的“让我们切断它并查看它是否仍然出错”),几天后,我们有了一个新版本的编译器和一个修复程序。很高兴知道你为编译服务合同付出的数千美元至少有时值得...

我的观点是,现代编译器可以容忍很多大型代码。 “兼容编译器必须至少支持”的最小限制。例如,我相信(从内存中再次),编译器需要在函数内支持127级嵌套语句(即127 if,switch,while和do-while的组合)。而且,从某个地方的讨论(这是“编译器应该支持127级嵌套语句”来自),我们发现MSVC和GCC都支持更多(足够我们放弃找到它... )

答案 2 :(得分:1)

C中有各种各样的实现定义限制。程序员有一些很好的定义和可见(想想数字限制),有些则没有。在我的标准草案副本中,第5.2.4.1节详细说明了这些限制的下限:

  

5.2.4环境限制

     

翻译和执行环境都限制了实现   语言翻译和图书馆。以下总结了与语言相关的内容   符合实施的环境限制;与图书馆有关的限制是   第7条讨论。

     

5.2.4.1翻译限制

     

实现应能够翻译和执行至少一个包含以下每个限制的至少一个实例的程序: 18)
   - 127个嵌套级别的块    - 63个有条件包含的嵌套级别    - 12个指针,数组和函数声明符(以任意组合)修改声明中的算术,结构,联合或void类型
  [...]

     
     

18)实施应尽可能避免强加固定的翻译限制。

我不能肯定地说你的翻译是否有可能触及其中任何一个,或者你所针对的C编译器即使你有问题,但我认为你可能会没事

至于错误:

Clang - http://llvm.org/bugs/buglist.cgi?bug_status=all&product=clang
 海湾合作委员会 - http://gcc.gnu.org/bugzilla/buglist.cgi?bug_status=all&product=gcc
 Visual Studio - https://connect.microsoft.com/VisualStudio/feedback

答案 3 :(得分:0)

听起来可能很明显,但真正了解的唯一方法就是通过测试。如果你不能自己做所有的努力,至少让你的产品跨平台,以便人们可以轻松地为你测试!如果人们喜欢您的项目,他们通常愿意免费提交错误报告甚至补丁:)