我在家庭作业上有这个问题(不用担心,已经完成):
[使用您最喜欢的命令式语言,举个例子
每个......]编译器既不能捕获也不能轻易生成代码的错误
catch(这应该违反语言定义,而不仅仅是a
程序错误)
来自“编程语言语用学”(第3版)Michael L. Scott
我的回答,打电话 main
从 main
通过传入相同的参数(在C和Java中),受到启发 这个。但我个人觉得这只是一个语义错误。
对我来说,这个问题是在询问如何产生既不是语法也不是语义的错误,坦率地说,我无法想到它也不会陷入其中的情况。
是否容易被利用的代码,如缓冲区溢出(以及我从未听说过的其他利用)?某种坑从语言结构中掉落(IDK,但懒惰的评估/弱类型检查)?我想在Java / C ++ / C中使用一个简单的例子,但欢迎其他例子。
未定义的行为 想起来。调用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 在语义上和语法上都是正确的但是使程序行为不规律。
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中的代码具有对于由另一个TU传递的某些输入值有条件地未定义的行为。我选择了一个略显模糊的,你可以轻松地使用无效指针解除引用或有符号整数算术溢出。
你可以说生成代码来捕获它是多么容易 - 我不会说它很容易,但编译器可能会注意到 ++a + ++b
如果是无效的 a
和 b
别名相同的对象,并添加相当于 assert (&a != &b);
在那条线上。因此,可以通过本地分析生成检测代码。