我喜欢从版本控制系统(VCS)中区分出三种不同类型的冲突:
- 文本
- 语法
- 语义
文本 冲突是由合并或更新流程检测到的。这由系统标记。在冲突解决之前,VCS不允许提交结果。
语法 冲突未被 VCS 标记,但结果无法编译。因此,即使是稍微仔细的程序员也应该注意到这一点。(一个简单的例子可能是通过 Left 重命名变量,然后 Right 添加使用该变量的行。合并可能会有一个未解决的符号。或者,这可能通过变量隐藏引入 语义冲突。)
最后,语义 冲突未被 VCS 标记,结果可以编译,但代码运行可能存在问题。在轻微的情况下,会产生错误的结果。在严重情况下,可能会导致崩溃。即使是这些冲突,也应该由非常仔细的程序员在提交之前通过代码审查或单元测试来检测。
我的语义冲突示例使用 SVN(Subversion)和 C++,但这些选择与问题的本质无关。
基础代码是:
int i = 0;
int odds = 0;
while (i < 10)
{
if ((i & 1) != 0)
{
odds *= 10;
odds += i;
}
// next
++ i;
}
assert (odds == 13579)
左 (L
) 和右 (R
) 的变化如下。
左边的“优化”(更改循环变量的值):
int i = 1; // L
int odds = 0;
while (i < 10)
{
if ((i & 1) != 0)
{
odds *= 10;
odds += i;
}
// next
i += 2; // L
}
assert (odds == 13579)
Right的“优化”(改变循环变量的使用方式):
int i = 0;
int odds = 0;
while (i < 5) // R
{
odds *= 10;
odds += 2 * i + 1; // R
// next
++ i;
}
assert (odds == 13579)
这是合并或更新的结果,不会被SVN检测到(这是版本控制系统的正确行为),因此它不是文本冲突。请注意,它可以编译,因此它不是语法冲突。
int i = 1; // L
int odds = 0;
while (i < 5) // R
{
odds *= 10;
odds += 2 * i + 1; // R
// next
i += 2; // L
}
assert (odds == 13579)
assert
失败是因为odds
的值为37。
我的问题是,是否存在比这更简单的例子?是否有一个简单的例子,编译后的可执行文件会崩溃?
作为一个次要的问题,你遇到过类似于这种在真实代码中出现的情况吗?同样,欢迎提供简单的例子。