我在家庭作业上有这个问题(不用担心,已经完成):
[使用您最喜欢的命令式语言,举个例子 每个......]编译器既不能捕获也不能轻易生成代码的错误 catch(这应该违反语言定义,而不仅仅是a 程序错误)
来自“编程语言语用学”(第3版)Michael L. Scott
我的回答,通过传递this启发的相同参数(在C和Java中)从main
调用main
。但我个人觉得这只是一个语义错误。
对我来说,这个问题是在询问如何产生既不是语法也不是语义的错误,坦率地说,我不能真正想到它不会陷入其中的情况。
是否容易被利用的代码,如缓冲区溢出(以及我从未听说过的其他利用)?某种坑从语言结构中掉落(IDK,但懒惰的评估/弱类型检查)?我想在Java / C ++ / C中使用一个简单的例子,但欢迎其他例子。
答案 0 :(得分:7)
这样做的一个例子是(来自维基百科页面)尝试修改字符串常量:
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
。因此,可以通过本地分析生成检测代码。