C ++局部变量生命周期异常行为

时间:2018-11-30 16:32:28

标签: c++ gcc

看看下面的代码片段。

struct s {
  char name[32];
};

void foo(bool x) {
  char *n = (char *) "Duke";
  if (x) {
      s tmp;
      strcpy(tmp.name, "Alice");
      //Uncomment the following to reveal the magic
      //printf("%s\n", tmp.name);
      n = tmp.name;
  }
  printf("%s\n", n);
}

foo(true)在取消注释if块内的 printf 语句和其他一些随机垃圾时,将字符串Alice打印两次。

可能是什么原因?

编译器信息:

编译器:G ++ 7.3

优化:O3

编辑:被称为“原始”帖子的链接无法回答我的问题,因为提供的链接涉及两个函数之间的交互,而我的问题专门涉及函数内块之间的交互。主要区别在于编译器处理程序堆栈的方式。

1 个答案:

答案 0 :(得分:4)

struct s {
  char name[32];
};

void foo(bool x)
{
    // char *n = (char *) "Duke";  // don't cast away const:
    char const *n = "Duke";
    if (x) {
        s tmp;
        strcpy(tmp.name, "Alice");
        //Uncomment the following to reveal the magic
        //printf("%s\n", tmp.name);
        n = tmp.name;
    }
    printf("%s\n", n);  // n points to tmp.name, which is gone now as *)
}

*)它是在块中定义的变量,该块是先前if语句的受控语句。其生存期以}结束该块而结束。变量超出范围。在生存期结束后通过指针访问tmp.nameundefined behaviour。指针不再保存有效的指针值。

printf("%s\n", n);

的很长的版本
puts(n);

不仅通过代码字符,而且还通过运行时开销。

治愈:

void foo(bool x)
{
    char const *n = "Duke";
    if (x)
        n = "Alice";
    puts(n);
}

严格治疗:

void foo(bool x)
{
    puts(x ? "Alice" : "Duke");
}