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

Java 既不是语法也不是语义的错误?,java,c++,c,syntax,semantics,Java,C++,C,Syntax,Semantics,我在家庭作业中遇到了这个问题(别担心,已经做完了): [使用您最喜欢的命令式语言,举例说明 每个…]都是一个编译器既无法捕获也无法轻松生成代码的错误 catch(这应该违反语言定义,而不仅仅是 程序错误) 摘自“编程语言语用学”(第三版)Michael L.Scott 我的回答是,从main调用main,方法是传入相同的参数(在C和Java中),灵感来自。但我个人觉得这只是一个语义错误 对我来说,这个问题是问如何产生一个既不是语法也不是语义的错误,坦率地说,我真的想不出它在哪种情况下都不会出现

我在家庭作业中遇到了这个问题(别担心,已经做完了):

[使用您最喜欢的命令式语言,举例说明 每个…]都是一个编译器既无法捕获也无法轻松生成代码的错误 catch(这应该违反语言定义,而不仅仅是 程序错误)

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

我的回答是,从
main
调用
main
,方法是传入相同的参数(在C和Java中),灵感来自。但我个人觉得这只是一个语义错误

对我来说,这个问题是问如何产生一个既不是语法也不是语义的错误,坦率地说,我真的想不出它在哪种情况下都不会出现

是不是代码容易受到攻击,比如缓冲区溢出(或者其他我从未听说过的攻击)?语言的结构中有某种缺陷(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 = %i\n", number, number * number);

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

调用未定义行为的语句在语义上和语法上都是正确的,但会使程序行为不稳定

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),那么
++a+++b
是无效的在那一行。因此可以通过本地分析生成检测代码。

我看到@Kninnug提供的Wikipedia页面上也有这个代码,我还没有想到有UB的语句会这么简单。@SGM1更简单的一个应该是
I=I++:)编译器可以捕捉到这个例子,只是一般情况下它们不需要麻烦。因此,在这个问题上需要做一些解释,它是想要一个编译器无法捕获的示例,还是仅仅是一个编译器无法捕获的示例,因为它不够聪明…@SteveJessop;但是,由于这些语句在语法上(语法上)是正确的,编译器不会将它们作为错误(一般而言)。@SteveJessop这也是由于未定义行为的定义:“使用不可移植或错误的程序结构或错误数据时的行为,本国际标准对此不作要求”。编译器不需要引发错误,甚至可能发生错误。
char*str=“Hello world!”不应该编译在C++中(不确定C),因为字符串字的类型是“代码> const char */COD>(实际上它通过数组到指针转换而衰减到……)@ MFH在C中,字符串文字没有<代码> const 类型。(尽管你仍然不允许对它们进行实际修改)。@ MFH:在C++中,字符串文本类型是“代码数组> const char < /C>”,但是在C中,它是“<代码> char < /代码>的数组”。因此,在C++03中,为了与C兼容,存在从字符串文本到
char*
的隐式转换。这种兼容性在C++03中被弃用,在C++11中被删除。所以,如果使用C++11,“不应该用C++编译”是正确的,而大多数人都不是。或者如果使用例如
-Wwrite strings-Werror
,大多数人不是,但可能应该是;-)在爪哇,几乎所有的故障都被一个异常信号所表明。这个问题似乎是偏离主题的,因为它属于这个不是C,这是C++。C没有参考资料。@ElchononEdelson:谢谢,修正了。我不知道我为什么写“C”:-)