我喜欢从版本控制系统 (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
) 更改如下。
Left '优化'(改变循环变量的值):
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)
正确的“优化”(改变循环变量的使用方式):
int i = 0;
int odds = 0;
while (i < 5) // R
{
odds *= 10;
odds += 2 * i + 1; // R
// next
++ i;
}
assert (odds == 13579)
这是合并或更新的结果,SVN 没有检测到(这对于 VCS 来说是正确的行为),因此它不是文本冲突。请注意,它可以编译,因此它不是句法冲突。
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。
所以我的问题如下。还有比这更简单的例子吗?有没有一个简单的例子,编译的可执行文件有一个新的崩溃?
作为第二个问题,您在实际代码中是否遇到过这种情况?同样,简单的例子特别受欢迎。