错误既不是语法也不是语义?

时间:2014-01-24 01:09:10

标签: java c++ c syntax semantics

我在家庭作业上有这个问题(不用担心,已经完成):

  

[使用您最喜欢的命令式语言,举个例子   每个......]编译器既不能捕获也不能轻易生成代码的错误   catch(这应该违反语言定义,而不仅仅是a   程序错误)

     
    

来自“编程语言语用学”(第3版)Michael L. Scott

  

我的回答,通过传递this启发的相同参数(在C和Java中)从main调用main。但我个人觉得这只是一个语义错误。

对我来说,这个问题是在询问如何产生既不是语法也不是语义的错误,坦率地说,我不能真正想到它不会陷入其中的情况。

是否容易被利用的代码,如缓冲区溢出(以及我从未听说过的其他利用)?某种坑从语言结构中掉落(IDK,但懒惰的评估/弱类型检查)?我想在Java / C ++ / C中使用一个简单的例子,但欢迎其他例子。

3 个答案:

答案 0 :(得分:7)

脑海中浮现出{p> Undefined behaviour。调用UB的语句在语法和语义上都不正确,但是代码的结果无法预测并被认为是错误的。

这样做的一个例子是(来自维基百科页面)尝试修改字符串常量:

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 = %i\n", number, number * number);

这里可能不一定有符号整数溢出。并且在编译或链接时不可能检测到它,因为它涉及用户输入。

答案 1 :(得分:5)

调用未定义行为 1 的语句在语义上和语法上都是正确的但是使程序行为不正常。

a[i++] = i;   // Syntax (symbolic representation) and semantic (meaning) both are correct. But invokes UB.   

另一个例子是使用指针而不初始化它 逻辑错误既不是语义错误,也不是语法错误。


<子> 1。 Undefined behavior:任何事情都可能发生;标准没有要求。程序可能无法编译,或者可能无法正确执行(崩溃或静默生成不正确的结果),或者它偶然可能完全符合程序员的意图。

答案 2 :(得分:2)

这是C ++的一个例子。假设我们有一个函数:

int incsum(int &a, int &b) {
    return ++a + ++b;
}

然后,下面的代码具有未定义的行为,因为它修改了一个对象两次而没有插入序列点:

int i = 0;
incsum(i, i);

如果对incsum的调用与函数定义的TU不同,则不可能在编译时捕获错误,因为代码中的任何一段都不是错误的在其自己的。它可以通过足够智能的链接器在链接时检测到。

您可以根据需要生成任意数量的示例,其中一个TU中的代码具有对另一个TU传递的某些输入值有条件地未定义的行为。我选择了一个略显模糊的,你可以轻松地使用无效指针解除引用或有符号整数算术溢出。

你可以说生成代码来捕获它是多么容易 - 我不会说这很容易,但编译器可能会注意到++a + ++b和{{1} a无效别名相同的对象,并在该行添加等效的b。因此,可以通过本地分析生成检测代码。