为什么C ++编译器在行之后而不是在它们之后给出错误? [英] Why does the C++ compiler give errors after lines instead of on them?

查看:229
本文介绍了为什么C ++编译器在行之后而不是在它们之后给出错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题今天在我的工作,当我还有另一个国内事情与我的编译器时弹出我的头。尽管我的buff粉红色(由于所有分号按我的工作),我设法错过一个如果语句。显然,这导致编译错误:


错误C2143:语法错误:缺少';'before'if'

$所以我想知道为什么你不能告诉我这行缺少分号而不是之后的行 问题。我继续尝试其他类似的语法错误:


错误C2065:'myUndeclared':undeclared identifier



错误C2143:语法错误:缺少')'before'if'



等...


< blockquote>

现在,所有这些错误,同样,我会在之后的问题,并抱怨在如果语句。



请考虑以下内容:

  SomeFunction(x)//注意,这里没有';'这里

if(bSomeCondition)
{
...
}

我遇到两个编译错误:


(第265行)错误C2065:'x':未声明的标识符



(第266行)错误C2143:语法错误: ';'before'if'


但是,第一个错误告诉我行号,尽管缺少分号。这告诉我,编译器不会在解析中跳起来,并且能够使它超过分号问题。那么,为什么编译器坚持用这种方式报告语法错误?其他错误(非语法)报告在他们找到的行。这是与编译器做多遍吗?基本上,我希望有一个C ++编译器工作知识的人具体解释编译器正在做什么,需要在这种之前的方式报告错误。

解决方案

为什么C / C ++错误消息吸吮是有时C ++真的很难解析(它实际上没有上下文无关语法)的更一般的问题的简短答案, 。但是,这不是一个有效的理由 - 仍然可以使工具记录比大多数C ++编译器更好的诊断信息。



更实际的答案是编译器作者继承了不重视错误消息的遗留代码库,结合轻度剂量的编译器作者懒惰,配以诊断报告不是一个令人兴奋的问题。大多数编译器编写器将添加一个新的语言功能或3%codegen性能改进,而不是在代码库上进行重大重构,以允许体面的错误报告。关于为什么没有正确地将错误本地化到导致他们的行的具体问题是这个的一个实例。没有真正的技术原因编译器一般不能解决一个; 缺少
,然后告诉你最后的源跨度; 缺少语句 - 即使存在C ++的一般空白不变性。



也就是说,新的编译器不会受到几十年的旧代码的影响。请查看 Clang编译器,它以明智的错误消息为傲。 诊断页面显示了比GCC好多少。这种情况的示例是:

  $ gcc-4.2 tc 
tc:在函数'foo':
tc:5:error:expected';'before'} token
$ clang tc
tc:4:8:error:expected b $ b ^
;

或更令人印象深刻的是:

  $ cat t.cc 
template< class T>
class a {}
class temp {};
a< temp> b;
struct b {
}
$ gcc-4.2 t.cc
t.cc:3:错误:在一个声明中有多个类型
t.cc:4:错误:非模板类型'a'用作模板
t.cc:4:错误:无效类型在声明之前';'令牌
t.cc:6:错误:预期未限定id在输入结束
$ clang t.cc
t.cc:2:11:error:expected';'after class
class a {}
^
;
t.cc:6:2:error:expected';'after struct
}
^
;

看,甚至告诉我们要输入什么来解决问题! < / clang_salespitch>


This question popped into my head today at work when I was having yet another domestic affair with my compiler. Despite my buff pinky (due to all the semicolon pressing I do at work), I managed to miss one before an if statement. Obviously, this resulted in a compile error:

error C2143: syntax error : missing ';' before 'if'

So I wondered "well gee, why can't you tell me the line that's missing the semicolon instead of the line after the problem." and I proceeded to experiment with other similar syntax errors:

error C2065: 'myUndeclared' : undeclared identifier

error C2143: syntax error : missing ')' before 'if'

etc...

Now, all of those errors would, similarly, take me to the line after the problem and complain about something before the if statement.

Consider the following:

SomeFunction(x) //Notice, there is no ';' here

if(bSomeCondition)
{
    ...
}

I get two compile errors:

(Line 265) error C2065: 'x' : undeclared identifier

(Line 266) error C2143: syntax error : missing ';' before 'if'

However, the first error correctly tells me the line number, despite the missing semicolon. This suggests to me that the compiler doesn't get tripped up in parsing and is able to make it past the semicolon problem. So, why is it that the compiler insists on grammatical errors being reported in this way? Other errors (non grammatical) are reported on the lines they are found. Does this have to do with the compiler making multiple passes? Basically, I hope someone with a working knowledge of the C++ compiler might explain specifically what the compiler is doing that necessitates the reporting of errors in this "before" way.

解决方案

The short answer to the more general question of "Why do C/C++ error messages suck" is "Sometimes C++ is really hard to parse" (it doesn't actually have a context free grammar). However, this isn't really a valid reason - one can still make tools that record better diagnostic information than most C++ compilers.

The more practical answer is "Compiler authors have inherited legacy codebases which didn't value error messages", combined with a mild dose of "compiler authors are lazy", topped with "Diagnostic reporting isn't an exciting problem". Most compiler writers would add a new language feature or 3% codegen performance improvement, rather than do significant refactoring on the codebase to allow decent error reporting. The specific question about "Why aren't errors properly localised to the line that 'caused' them" is an instance of this. There's not really a technical reason compilers can't generally work out that a ; is missing , and then tell you about the source span of the last ; lacking statement - even in the presence of C++'s general whitespace invariance. It's just that storing that information has (largely) been historically ignored.

That said, new compilers not hampered by decades of old code are doing much better. Have a look at the Clang compiler, which prides itself on sensible error messages. The page on diagnostics shows how much better than GCC they are. An example for this case being:

  $ gcc-4.2 t.c
  t.c: In function 'foo':
  t.c:5: error: expected ';' before '}' token
  $ clang t.c
  t.c:4:8: error: expected ';' after expression
    bar()
         ^
         ;

Or, more impressively:

  $ cat t.cc
  template<class T>
  class a {}
  class temp {};
  a<temp> b;
  struct b {
  }
  $ gcc-4.2 t.cc
  t.cc:3: error: multiple types in one declaration
  t.cc:4: error: non-template type 'a' used as a template
  t.cc:4: error: invalid type in declaration before ';' token
  t.cc:6: error: expected unqualified-id at end of input
  $ clang t.cc
  t.cc:2:11: error: expected ';' after class
  class a {}
            ^
            ;
  t.cc:6:2: error: expected ';' after struct
  }
   ^
   ;

Look, it's even telling us what to type where to fix the problem! </clang_salespitch>

这篇关于为什么C ++编译器在行之后而不是在它们之后给出错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆