缺乏编译器错误词汇表使新手程序员感到沮丧


66

我一家人的朋友在学习编程(用C语言)时向我寻求帮助。在我们交谈时,他对很难理解自己的编译器(GCC)在出错时向他发送的错误消息感到沮丧。他不理解所有使用的术语,有时是它们的组合超出了他的理解。他问我:“编译器文档为什么不包含对错误消息的更长解释?” 我对他没有一个好的答案。

我本人-作为一个经验丰富的程序员-在这种情况下很少见,但那些罕见的情况确实发生了-我以前从未遇到过的一些奇怪的错误消息。我设法在搜索引擎中查找错误消息,但是显然这并不总是对他有用-尤其是因为他遇到的错误更常见并且发生在多个不同的情况下,这与他的问题有关拥有。

那么,新手程序员应该如何应对理解编译器错误消息的挑战?具体来说,结合C和GCC?


7
“那么,新手程序员应该如何应对理解编译器错误消息的挑战?” / sarcasm所需的第一个技能是能够从编译器消息中读取所有位,包括将其与上下文关联。/讽刺。它很少被证明是编译器中的缺陷或错误。
πάνταῥεῖ

10
@MasonWheeler:新手在接受培训时通常不会选择使用哪个编译器。GCC是许多系统的共同点...
einpoklum

24
当涉及到GCC C ++模板错误时,我发现是否在“ Error <file:line>”之后停止阅读并研究了源文件,所以我发现错误的速度更快,并且具有保持理智的副作用。如果我读了GCC给出的实际错误.....
mattnz

18
解决方案很明显:使用输出混乱较少的编译器。我建议使用rmcc。它会打印Yes.还是No.取决于您的代码是否已编译。立即消除不理解冗长无意义的消息所带来的挫败感!
管道

21
对于初学者来说,C语言不是一门好语言-您偶然发现了其中一个原因。话虽这么说,Clang倾向于提供更好的错误,对于初学者来说也可能更有吸引力。
Theodoros Chatzigiannakis

Answers:


164

一些有用的技术:

  • 打开-Wall-Werror。当您难以理解破译错误消息以创建更多错误消息时,这似乎是违反直觉的,但是警告通常更易于理解并且更接近问题的实际根源,而忽略这些警告可能会导致难以理解的错误。 。
  • 只需尝试修复列表中的第一个错误即可。错误通常相互叠加,导致以后的错误消息并不是真正的实际错误。修复一个并重新编译。当您获得更多经验时,将能够更好地修复多个错误消息。
  • 尽可能使用最新的编译器版本。C是一种非常稳定的语言。因此,更新的编译器中很大一部分改进不是添加语言功能,而是改善开发人员体验,包括更好的错误消息。默认情况下,许多广泛使用的linux发行版都具有非常旧的gcc版本。
  • 逐步编程。编译前不要尝试编写大量代码。编写尽可能少的数量,仍然可以编译。如果自上次干净编译以来仅更改了一行,则找出哪一行包含实际问题要容易得多。
  • 编写单元测试。它使您更有信心在修复编译错误时进行清楚的重构更改。

23
良好的IDE也可以极大地帮助提高体验,例如。强调红色错误。
BlueRaja-Danny Pflughoeft

86
“增量编程。在编译之前不要尝试编写大量代码。写尽可能少的代码仍然可以编译。如果自上次干净编译以来仅更改了一行,那么找出来就容易得多哪一行包含实际问题。” 这个,这么多。另外,如果您编写的代码无法编译,大多数IDE都会警告您,并突出显示错误。
Polygnome

4
@einpoklum:不要小看第三个选择;编译器错误消息已改善很多。同样,使用多个编译器(例如gcc和clang)-捕获更多错误/警告,并且其中一个可能对另一个问题的诊断要强于另一个。
马太福音

19
@einpoklum:特别是对于初学者,渐渐地编写东西是非常重要的。哎呀,如果你相信“短编程作业”不能逐步完成,他们的分裂成几个小功能,落实并一个接一个编译它们,你应该设法提高该技能为自己..
布朗博士

4
一个帮助我的技巧:如果错误消息提到N行,请检查N-1行。例如,如果您在第17行缺少分号,则错误消息将指出第18行有问题。这是因为编译器期望分号,但在下一行得到了其他内容。
user2023861

56

您的朋友不需要词汇表。 词汇表不会帮助他。他需要的是更好的直觉,即发生编译器错误时该怎么办。

C编译器错误不像C#编译器错误那样直观,由于许多原因,大多数原因与C的“接近金属”性质有关。解决C中的编译器错误不是模式匹配练习,因为错误接收可能与实际问题无关。与通常将错误消息映射到精确的代码位置和问题的C#或Java不同,C语言中的错误很可能是众多而遥远的。

这样的一个例子是“期望以分号表示”或任何数量的语法错误,这些错误表明解析器挂在某种东西上(不一定是分号)。或类似“意外的前向声明”之类的错误,当我看到此错误时,总是表示我的一个.h文件中的大写错误,但并未指出.h文件是问题的根源。

您朋友的策略不应该是将其与错误和解决方案列表进行模式匹配;应该足够了解C语言的语法和规范,才能弄清楚实际问题是什么。


17
否。我们的想法是充分了解该语言,知道您不能对数字表达式进行赋值,而只能赋给变量。您根本不需要知道什么是左值,这就是为什么他们在初学者课程中不教它。
罗伯特·哈维

18
本质上是。但是实际上,这是不可能的。我这样做已经很长时间了,每次编写C程序时,我仍然会得到模糊的编译器错误消息。但是,我很少去阅读这些信息并试图理解它们。相反,我查看错误消息指向的位置,并且因为我知道C程序的基本语法结构应该是什么样,所以我可以相对迅速地发现问题,而无需花费时间来解读错误消息。
罗伯特·哈维

36
换句话说,要求词汇表来理解编译器错误有点像阅读字典来理解英语。这不是很有效。您通过阅读和编写英语而不是阅读词典来学习和理解英语。
罗伯特·哈维

14
[耸耸肩] 如果您不使用字典只是为了补充已经存在的英语知识,我建议您做错了。我要说的最后一件事是,使新手程序员比以往任何时候都更迷上词汇的东西。程序员不需要更多的单词。他们需要更多技能。
罗伯特·哈维

13
@einpoklum,词汇表在这里无济于事。对于初学者来说,“左值”一词的描述可能太过技术性,或者沿用了“在作业的左手边可以有什么”之类的词,这同样无济于事。
Bart van Ingen Schenau,

26

值得一提的相关技术是使用第二个编译器。例如,Clang已投资了更好的错误消息,但是任何表达错误的替代方法都可以启发人。

对于最复杂的错误类型尤其如此。例如,当您混合使用两个类似的结构(对于初学者来说并不常见)时,编译器通常会在生成正确的错误消息时遇到问题。当您实际上打算构造B时,当编译器给出关于构造A的不正确使用的错误消息时,这可能引起混乱。第二个编译器可能会推断您想要B。


13

不久前有人在Wikibooks上尝试过GCC错误词汇表,但看起来它从未完全起飞并且尚未更新。

“错误”部分比“警告”部分远得多。看起来它是针对G ++的,但是那里的朋友仍然有一些有用的信息。


12

除了上述答案外,请注意,大多数编译器没有全面的错误词汇表-由于消息本身经常更改,因此需要维护很多工作,并且其中有很多。

词汇表的最佳替代品是访问互联网。每当编译器产生您不理解的错误时,请放心,您极不可能是第一个遇到该错误并感到困惑的人。快速搜索准确消息的Google通常足以为您提供易于阅读的格式的大量信息,并且其示例代码与您自己的示例代码非常相似。

除此之外,您还需要时间和对语言以及编译器的熟悉。那,以及卡尔·比勒费尔特(Karl Bielefeldt)给出的好的建议


1
我认为维护工作不会很多。另外,它可以由Stackoverflow或Wiki之类的公众添加,并向受信任的人提供编辑权限。
einpoklum

6
@einpoklum您是否看过PHP文档?当您让社区照顾这些东西时,就会发生这种情况。
凯文

4
从前,出版(印刷)的手册是唯一可用的资源。他们通常写得足够好,以提供解决问题所需的信息/指南。随着互联网的发展,已经没有人出版印刷品了(如果有的话,它是在线的)。在我编写程序的几十年中,“官方”参考资料(在线或其他方式)的质量已大大下降,因此,最佳的可用资源通常是Google,而最有用的结果通常出现在Stackoverflow中。
Zenilogix

2
即使词汇表确实存在,搜索引擎可能会访问他们的最好方式。当您在未知的地区时,它们也很有用:当唯一的搜索结果是定义错误消息的源代码时;)
Warbo,

2
在大学里,我曾经遇到过编译器错误“ Dave认为不应该这样。请通过<dave@example.com>向他发送电子邮件”。我给他发了电子邮件,实际上我是第一个遇到该特定错误的人!
user1118321

6

C标准以与其他编程语言不同的方式使用诸如“左值”和“对象”之类的许多术语,并且编译器消息通常以此类术语编写。在本标准的某些部分中,术语的使用不一致,但是任何想学习C的人都应该查看C89,C99和/或C11标准的草案以及其基本文件。搜索“ C99草稿”或“ C89基本原理”应该可以很好地进行,尽管您可能需要确保获得所需的文档。尽管大多数编译器都支持C99标准,但了解它与C89标准的不同之处可能会很有用,并且C89的原理可能会提供某些历史背景,而更高版本则没有。


11
C标准是非常密集和沉重的文字。初学者没有机会了解它。
NieDzejkob '18年

4
@NieDzejkob:编译器使用的术语(似乎就是问题所在)源自标准。尽管您没错,该标准的某些部分令人难以理解(部分原因是它是由委员会设计的,并且作者似乎对该标准的各个部分的含义没有一致的理解),但是任何想了解什么的人像“左值”之类的术语应注意它们的来源。此外,如果要了解为什么会x=0x1e-x产生错误,我真的不知道标准以外的内容……
supercat

3
我同意@NieDzejkob的观点:C标准不是您想面对新手的那种文本。新手需要快速积极的动手体验。当他们弹出时,他们需要逐一学习新事物。阅读标准或基本原理会花费太多时间,同时会使新手完全不知所措。
cmaster

2
@cmaster:我很早以前就使用C89 Standard,即使在浏览器具备方便的“查找文本”功能的日子里也还不错。我同意以后的标准越来越差。尽管没有人应该依靠该标准作为唯一参考,但重要的是要认识到民间对微型计算机编译器行为的看法与标准允许低质量行为的方式之间的分歧,因此,如果有对付后者。
超级猫

3
@cmaster:在任何情况下,使用C语言进行编程的人都应该了解该标准,并且知道如何在需要时查阅该标准,即使他们不打算阅读全部内容。例如,如果有人在网络上搜索标准库功能,则可能会找到一种引用来描述某个实现在某些极端情况下的行为,而没有从标准的角度提及那些极端情况会调用未定义行为,而其他实现可能不能以相同的方式工作。如果改为搜索标准,则可以避免该问题。
超级猫

5

我很惊讶没有人给出明显的答案,而且我怀疑这是实践中最常用的答案:只是不阅读错误消息。

大多数错误消息的价值中的绝大部分只是在某条这样的线路上出现了问题。大多数时候,我只是查看行号并转到该行。那时,我对错误消息的“阅读”通常只是我通过时所注意的,甚至不是掠过的内容。如果不能立即弄清线路上或线路附近出了什么问题,那么我将实际阅读该消息。使用IDE或工具突出显示错误并自动完成Karl Bielefeldt的建议,即只考虑较小的更改,此工作流程甚至更好。

当然,错误消息并不总是指向适当的行,但是它们也常常也不指向适当的根本原因,因此,即使是对错误消息的充分理解也将提供有限的帮助。很快就可以知道哪些错误消息对于定位正确的行更可靠。

一方面,大多数的错误是新手很可能使有可能是痛苦明显没有从编译器是必要的帮助有经验的程序员。另一方面,对于新手来说,它们变得如此明显的可能性要小得多(尽管许多缺陷是显而易见的,但大多数错误都是愚蠢的错误)。在这一点上,我完全同意Robert Harvey的观点,新手只需要对这种语言更加熟悉。这是不可避免的。引用了不熟悉的概念或看起来令人惊讶的编译器错误应被视为加深对语言知识的提示。同样,在编译器抱怨但您看不到代码为什么错误的情况下。

再次,我同意Robert Harvey的观点,即需要一种更好的利用编译器错误的策略。我已经在上面概述了一些方面,Robert Harvey的答案也提供了其他方面。甚至不清楚您的朋友希望如何使用这样的“词汇表”,而且这样的“词汇表”实际上不太可能对您的朋友有用。编译器消息当然不是介绍语言1概念的地方,“术语表”并不是更好的地方。即使对错误消息的含义进行了清楚的说明,也不会告诉您如何解决问题。

1但是,有些语言(例如Elm和Dhall(可能还有Racket))以及一些“面向初学者”的语言实现确实尝试这样做。从这个角度来看,MSalters建议使用不同的实现方式是直接相关的。我个人认为这样的事情令人信服,而且并不是针对正确的问题。这并不是说没有办法编写更好的错误消息,但是对我来说,它们倾向于围绕使编译器的信念和这些信念的基础更加清晰。


4

那么,新手程序员应该如何应对理解编译器错误消息的挑战?具体来说,结合C和GCC?

告诉您的朋友遇到他们不了解的错误时,请执行以下操作:

  • 删除/注释自上次成功构建以来添加的代码。
  • 放回一小部分并进行编译
  • 重复直到发生错误

编译器错误仅告诉您编译器对您的代码不了解的内容,而不是对代码有何疑问。这种方法所花费的时间与Google搜索错误并阅读一些文档或StackOverflow帖子所花费的时间大致相同,但是可以更好地了解您做错了什么。

还要使它们经常进行编译,直到他们开始处理需要花费几分钟才能构建的项目,并在添加太多其他代码之前发现错误会有所帮助。

最后,告诉他们一次处理一件事情,不要在没有编译的情况下处理多个文件,不要一次引入多个依赖项,等等。


4

另一种技术是让朋友在遇到不同的错误消息时随时间编写自己的词汇表。学习某物的最好方法通常是教它。当然,到词汇表完成时,他可能将不再需要它。

我对GCC的个人经验是,每个错误消息都与一组“正常”错误相关。例如,当GCC说“您忘记了&”时,通常意味着我忘记了括号。当然,哪些错误对应于哪些错误消息将取决于程序员,这也是朋友编写自己的词汇表的另一个很好的理由。


1
该文档具有非常重要的附带好处,可以在线发布(即使只有5-10个条目),也可以在申请实习时与众不同。
Josh Rumbut
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.