【问题标题】:VS2019 | C++ | Shared Pointers | Compiler Warning: The pointer points to memory allocated on the stackVS2019 | C++ |共享指针 |编译器警告:指针指向堆栈上分配的内存
【发布时间】:2022-01-23 21:38:53
【问题描述】:

我继承了一堆 C++ 代码,其中充满了 std::shared_ptrs,其中大多数 [all?] 都是不必要的,而且我怀疑它们会降低性能。一口气改完所有东西是不可行的,所以我分批改代码,做性能测试。

我遇到的一个问题是我的新“原始”指针代码和底层 shared_ptr 内容之间的方法层次结构中的接口。一个人为的例子(我知道它可以被简化......):

SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
  //for the underlying shared pointer methods
  std::shared_ptr<std::string> tmpString = make_shared<std::string>(aString);

  //call the method using my local shared pointer
  std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);

  //The line below gives compiler warning: "The pointer points to memory allocated on the stack" 
  return someObj.get(); // a pointer to an object in std::map
}

知道GetTheObject() 正在返回一个指向持久化std::map 中的对象的指针,因此在我们退出GetSomeObject() 和共享指针[和其包装的原始指针] 已超出范围。

我没有忽视警告的习惯,所以:

问题:

  1. 警告是因为编译器担心共享指针的范围而不是指向的对象吗? [IE。在这种情况下我可以忽略它吗?]

  2. 如果这是一个真正的问题,是否有任何巧妙的方法解决这个问题(不涉及构建包装类和此类解决方法......)?

【问题讨论】:

  • someObj 会尝试删除对象,这是一个真正的问题。
  • 我很困惑您认为将shared_ptr 的使用更改为原始指针会带来什么性能改进。这个 sn-p 至少不会有任何收获,因为它仍然首先复制 shared_ptr 导致引用计数增加(并在返回时减少)
  • 你好@apple apple:在进一步的调查[断点,观察窗口]中,return someObj.get(); 正在返回我怀疑/希望的内容:存储在持久性@中并从中检索到的对象的地址987654329@ 在GetTheObject(...) 调用中访问。并且此地址已成功传递给调用方法。显然,检索到的地图对象本身并不是删除的目标。因此,除非还有其他问题需要考虑,否则“GetSomeObject(...)”会返回一个完全有效的内存地址...或者在我看来是这样???
  • 您得到一个存储在someObj 中的指针,然后someObj 立即超出范围。 shared_ptr 销毁时做了什么?
  • 你好@BoP:同样的论点适用于任何返回指针的本地定义的构造,不是吗?手头的问题是目标内存本身是否超出范围。在我的情况下,它没有。我不知道内部结构 - 但malloc 分配内存并返回指向该内存的指针。 malloc 不是系统调用,所以我认为它使用超出范围的局部变量 - 但它返回一个有效指针,指向分配给用户代码中的指针的有效内存块,并且可以向上传递调用链并且仍然完全有效。想法?

标签: c++ visual-studio-2019 shared-ptr compiler-warnings


【解决方案1】:

如果我的理解正确,您将在 2021 年将智能指针替换为哑指针,而您现在正面临智能指针打算解决的确切问题。

警告是 100% 准确的,我很惊喜编译器看起来足够深入。

解决方案很简单:返回一个shared_ptr&lt;SomeObject&gt;。如果您想提高效率,有两个真正的可能的改进。 C++11 引入了移动构造函数和moving shared_ptr is faster than copying。编译器将对return someObj; 使用移动ctor,因为someObj 超出范围

其次,shared_ptrunique_ptr 的重量级替代品。有时,您可以降级到后者。

【讨论】:

  • 您好@MSalters:感谢您的回复。你能解释一下共享指针应该解决的问题吗?我 [公认有限] 的理解是他们解决了垃圾收集问题:newdelete 等等。我已经使用静态变量和计数器来获得相同的结果......我的问题是代码性能不佳,必须运行得更快才能使用。共享指针是调查的一部分,可能相关也可能不相关。在 2021 年是否可以使用原始指针并不困扰我!感谢您提供有关唯一指针的信息。我去看看。
  • 忘记了:还有一件事:见回复@“apple apple”。该代码实际上的工作原理是将指向有效内存的有效指针传递回调用GetSomeObject()的函数...
  • 嗯,指针无效有效,“apple apple”是对的;内存已被释放到免费存储区(但可能不会一直回到操作系统)。它还没有崩溃。智能指针以及vcetor&lt;T&gt;string 等类允许您将可变大小的分配视为像int 这样的普通值。它不是像 Java 或 .Net 这样的垃圾收集。 someObj 仍然超出您的代码范围,并且没有 GC 接管该内存的责任。
【解决方案2】:

我的项目中有类似的代码。我同意正确的解决方案可能只是完全致力于智能指针并正确使用它们。但是,我不想翻阅成堆的功能完善的代码,但我也希望警告消失。我能够通过以下方式解决警告:

SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
  //for the underlying shared pointer methods
  std::shared_ptr<std::string> tmpString = make_shared<std::string>(aString);

  //call the method using my local shared pointer
  std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);

  SomeObject *pRet = someObj.get();
  return pRet; // a pointer to an object in std::map
}

我有点担心编译器会在某个时候变得更智能,并将其检测为警告,但目前看来还可以。 (Visual Studio 2022 v17.1)希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 2021-12-09
    • 2020-07-26
    相关资源
    最近更新 更多