strcpy(m + 1,m)的不可预测的行为

时间:2016-05-18 02:46:21

标签: c gcc segmentation-fault

我正在研究有关seg故障的例子:

char m[10]="dog";
strcpy(m+1,m);

在我的centOs机器中,结果如预期:分段错误。但在Ubuntu上没有任何事情发生。然后我添加一个printf(“%s”,m);对于ubuntu上的代码而且令人惊讶的是我得到了“ddog”作为结果。 我正在使用GCC,ubuntu版本是最新版本。 任何人都可以告诉我为什么结果不同。我也用raspbian检查它,我也收到了分段错误。

谢谢,

2 个答案:

答案 0 :(得分:3)

这导致undefined behaviourstrcpy只能在不重叠的区域之间使用。

要修复此代码,您可以写:

memmove(m+1, m, strlen(m) + 1);

答案 1 :(得分:1)

m的内存是:

+---+---+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+---+---+

用初始化它:

char m[10] = "dog";

初始化前四个元素m。其余的都已初始化。

+---+---+---+----+---+---+---+---+---+---+
| d | o | g | \0 | ? | ? | ? | ? | ? | ? |
+---+---+---+----+---+---+---+---+---+---+

我正在使用?来表示未初始化的内存位置。他们可以 包含任何东西。

让我们来看看

的执行情况
strcpy(m+1, m);

一步一步。

第1步:将m[0]复制到m[1]。所以你有:

+---+---+---+----+---+---+---+---+---+---+
| d | d | g | \0 | ? | ? | ? | ? | ? | ? |
+---+---+---+----+---+---+---+---+---+---+

第2步:将m[1]复制到m[2]。所以你有:

+---+---+---+----+---+---+---+---+---+---+
| d | d | d | \0 | ? | ? | ? | ? | ? | ? |
+---+---+---+----+---+---+---+---+---+---+

第3步:将m[2]复制到m[3]。所以你有:

+---+---+---+---+---+---+---+---+---+---+
| d | d | d | d | ? | ? | ? | ? | ? | ? |
+---+---+---+---+---+---+---+---+---+---+

strcpy在遇到源中的空字符时终止 论点。如您所见,strcpy的终止条件永远不会 得到满足。因此,程序继续从内存中读取数据 有效限制并将数据写入超出有效限制的内存。

这是未定义行为的原因。

要获得所需的结果"ddog",您可以使用:

size_t len = strlen(m);
for ( int i = len; i >= 0; --i )
{
   m[i+i] = m[i];
}