错误既不是句法也不是语义?
我有一个家庭作业的任务(不用担心,已经完成):
[使用你最喜欢的命令式语言,给出每个例子......]编译器既不能捕捉也不能轻易生成代码来捕捉的错误(这应该违反语言定义,而不仅仅是程序错误)
从“编程语言语用学”(第3版)Michael L. Scott
我的答案是,通过传递相同的参数(在C和Java中),从这里启发,从main
调用main
。 但我个人觉得这只是一个语义错误。
对我来说,这个问题是如何产生一个既不是句法也不是语义的错误,坦率地说,我不能真正想到它不会陷入其中的情况。
它会是易受开发影响的代码,如缓冲区溢出(也许还有其他我从未听说过的开发)? 语言结构(IDK,但懒惰的评估/弱类型检查)会有某种陷阱? 我想用Java / C ++ / C中的一个简单示例,但欢迎其他示例。
未定义的行为值得思考。 调用UB的语句在语法和语义上都不正确,但是代码的结果不能被预测并被认为是错误的。
一个例子是(从Wikipedia页面)试图修改一个字符串常量:
char * str = "Hello world!";
str[0] = 'h'; // undefined-behaviour here
并非所有的UB声明都很容易识别。 例如,考虑在这种情况下签名整数溢出的可能性,如果用户输入的数字太大:
// get number from user
char input[100];
fgets(input, sizeof input, stdin);
int number = strtol(input, NULL, 10);
// print its square: possible integer-overflow if number * number > INT_MAX
printf("%i^2 = %in", number, number * number);
这里可能不一定是有符号整数溢出。 由于涉及用户输入,因此无法在编译或链接时检测到它。
调用未定义行为 1的语句在语义上和语法上都是正确的,但会使程序行为不正常。
a[i++] = i; // Syntax (symbolic representation) and semantic (meaning) both are correct. But invokes UB.
另一个例子是使用一个没有初始化它的指针。
逻辑错误既不是语义也不是句法。
1.未定义的行为:任何事情都可能发生; 该标准没有规定任何要求。 程序可能无法编译,或者它可能执行不正确(崩溃或无声地产生不正确的结果),或者它可能偶然地按照程序员的意图执行。
这是一个C ++的例子。 假设我们有一个函数:
int incsum(int &a, int &b) {
return ++a + ++b;
}
然后下面的代码有未定义的行为,因为它修改了一个对象两次,没有中间顺序点:
int i = 0;
incsum(i, i);
如果对incsum
的调用与函数的定义不同,则不可能在编译时捕获错误,因为这两个代码本身都是天生错误的。 它可以在链接时被足够智能的链接器检测到。
您可以根据需要生成任意数量的示例,其中一个TU中的代码具有对另一个TU传递的某些输入值有条件未定义的行为。 我去了一个稍微模糊的地方,你可以轻松地使用一个无效的指针解引用或一个有符号的整数算术溢出。
你可以争辩说,生成代码是多么简单 - 我不会说这很容易,但编译器可能会注意到,如果a
和b
别名相同的对象,则++a + ++b
无效,并且添加相当于assert (&a != &b);
在那一行。 所以检测代码可以通过本地分析生成。