【问题标题】:Can I end up with a pointer to an unintended location by passing a pointer to a stack variable to a function in C++?我可以通过将指向堆栈变量的指针传递给 C++ 中的函数来获得指向意外位置的指针吗?
【发布时间】:2013-05-14 00:51:27
【问题描述】:

我知道编译器优化有时会导致堆栈帧波动。所以我的问题是,在 c++ 中创建堆栈指针并将其传递给另一个函数并期望它指向被调用者中的同一个对象是否总是安全的。由于编译器优化,是否有可能最终指向一个意外的位置。

例如,这对于任何编译器来说总是安全的吗?

int main(){
   std::ofstream f("somefile");
   foo(&f);
   return 0;
}

或者我应该使用堆来获得一致的结果。

int main(){
   std::ofstream *f=new std::ofstream("somefile");  
   foo(f);
   close(*f);
   delete f;
   return 0;
}

【问题讨论】:

  • 您的第一个示例甚至无法编译。
  • 优化不应该将正确的代码转换为不正确的代码(编译器从正确的代码生成不正确的程序是有问题的)。您可能关心的是:“我的代码是否正确,编译器优化会产生正确的结果”。
  • @LucDanton 你有没有听说过程序员抱怨他们的代码在一个系统上工作多年,然后突然停止工作,要么是因为新的系统/编译器,要么是编译器的行为不同?
  • @MoZo:只有当编译器或代码包含错误时才会发生这种情况。如果代码不正确,则无论是否仅在使用优化编译器时才显示都是不正确的,如果代码正确,则如果优化后没有产生正确的结果,则是编译器中的错误。 Luc Danton 指出“因为编译器优化”并不是代码从正确变为错误的正当理由。
  • 请注意,我说的是“正确的代码”,而不是“有效的代码”。这也应该是您关心的问题之一! (总而言之,我并不是说没有错误的编译器或工具;但您无法通过编码摆脱这些。)

标签: c++ object heap-memory stack-memory


【解决方案1】:

当存在指向生命周期已结束的对象的指针时,将创建 dangling pointer

std::string* s;
{
    std::string s1("hello");
    s = &s1;
}
// 's' now a dangling pointer because 's1' has been destructed.

发布的代码 sn-ps 中都不存在这种情况,因此两者都是安全的。 (虽然第一个更好,因为它避免了不必要的动态内存分配)。

【讨论】:

  • 再看一遍,第一个示例无法编译,因为他们试图用字符串指针初始化ofstream 指针。
  • 除了第一个甚至不会编译。
  • 我对 c 编程的理解是,将指向堆栈位置的指针传递给另一个函数是不安全的,因为编译器可以优化代码,因此,您的指针最终可能指向一个意外地点。这就是我所说的悬空指针的意思。
  • @juanchopanza,是的,我知道。我更多地关注编译错误的悬空指针问题。
  • @MoZo,只要在使用指针期间保留指针所指的对象,就可以安全地传递指针。
【解决方案2】:

在块中定义的对象的生命周期延伸到块的末尾,这取决于在对象定义和块的末尾之间调用了哪些函数。因此,您的第一个示例没有问题。

您可能对相反的方法感到困惑:返回指向函数本地对象的指针是安全的:

std::ofstream * foo() {
  std::ofstream f("somefile");
  return &f;
}

int main() {
  std::ofstream * f = foo();
  // At this point there's no guarantee that f points to a valid object
}

【讨论】:

  • 我想将其改写为“因此您的第一个示例没有问题,如果foo 没有副作用,例如存储指针值”。
  • 你是对的,但是如果它确实是我上面示例的一个更复杂的实例。换句话说,foo() 不应将指针值存储在其生命周期延长 foo() 本身的对象中。
猜你喜欢
  • 1970-01-01
  • 2013-04-14
  • 2010-10-13
  • 2020-01-03
  • 1970-01-01
  • 2019-06-12
  • 2012-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多