【问题标题】:Core Dump When Retrieving From Templated Queue从模板化队列中检索时的核心转储
【发布时间】:2017-04-18 23:21:27
【问题描述】:

背景

我想要一个类MyClass 来存储不同类型的队列。为此,我创建了一个接口ValueInterface 和一个派生类Value<T>。我现在可以使用queue<ValueInterface> 成员变量将这个派生类的实例存储在MyClass 中。

注意:出于我自己的目的,我故意尝试将MyClass 保持为非模板化,并且我想依赖模板化函数。

目标

我有下面的代码可以编译,但在下面的测试代码中运行会导致核心转储。我认为我在使用std::unique_ptr 时要小心,并确保在可能的情况下使用std::moveGetValueAndAdvance<T> 函数会导致错误。当我尝试从模板化队列中检索时出现问题。我知道这很混乱,我假设 static_cast 可以工作,但是我怎样才能从存储 ValueInterfacestd::queue 中检索 Value<T> p>

我不知道问题出在StoreValueGetValueAndAdvance 上,还是整个设计存在缺陷,无法在类型敏感的语言中实现。

在测试中的使用: 这是我想要完成的功能。这是假设每个MyClass 一次只能用于一种类型。所以让我们假设没有人会在同一个MyClass 对象上调用StoreValue<int>(4)StoreValue<string>("hello")。但出于我自己的原因,我想保留MyClass 非模板化。

 MyClass my_class;
 my_class.StoreValue<int>(5);
 int val;
 my_class.GetValueAndAdvance<int>(&val);
 std::cout << "value: " << val; // Should print "value: 5"

代码:

class ValueInterface {};

template <class T>
class Value : public ValueInterface {
 public:
  Value(T val) : value_(val){};
  T get() { return value_; }

 private:
  const T& value_;
};

class MyClass {
 public:
  template <class T>
  void GetValueAndAdvance(T* out_val) {
    if (!queued_values_.empty()) {
      auto unique_value = std::move(queued_values_.front());
      queued_values_.pop();
      auto unique_value_typed = static_cast<Value<T>*>(unique_value.get());
      *out_val = unique_value_typed->get();
      // Prints 0 even though it should return 5 based on the test code (below)
      std::cout << "value: " << unique_value_typed->get(); 
    }
    return;
  }

  template <class T>
  MyClass* StoreValue(const T& value) {
    auto wrapped_value = std::make_unique<Value<T>>(value);
    queued_values_.push(std::move(wrapped_value));
    return this;
  }

 private:
  std::queue<std::unique_ptr<ValueInterface>> queued_values_;
};

错误消息的 sn-p

F0418 18:08:57.928949  244111 debugallocation.cc:763] RAW: delete size mismatch: passed size 1 != true size 4
    @     0x7fda024f8a1f  (anonymous namespace)::RawLogVA()
    @     0x7fda024f8525  base_raw_logging::RawLog()
    @           0x42b162  tc_delete_sized
    @           0x40c595  std::default_delete<>::operator()()
    @           0x40c503  std::unique_ptr<>::~unique_ptr()
    @           0x40b552  mynamespace::MyClass::GetValueAndAdvance<>()

【问题讨论】:

    标签: c++ templates c++14 unique-ptr coredump


    【解决方案1】:

    Value 类中存在问题,其中 value_ 被定义为对常量值的引用

    const T& value_;
    

    value_ 定义为正常(非参考)值

    const T value_;
    

    你应该从std::cout得到5

    观察Value&lt;T&gt;的构造函数

    Value(T val) : value_(val){};
    

    value_ 引用使用(绑定到)一个 临时 变量 (val) 进行初始化,该变量在构造函数末尾超出范围。

    所以value_ 绑定到一个可以重用的内存,所以有未定义的值。

    【讨论】:

    • 抱歉,这并没有解决问题 :( 见上文,我更新了帖子以包含我的错误消息的 sn-p。
    • @user3445268 - 可能还有另一个问题,但确实是个问题(删除引用,用我的编译器打印5);您应该向我们提出一个最小但完整且可编译的示例,以使我们能够重现该问题。
    • 嗨@max66,我已经调查过了,发现我的编译器比你的要挑剔得多。在运行时,它不知道要删除什么大小的对象,因为我一开始只有一个 ValueInterface 对象。修复方法是在 ValueInterface 类中添加一个虚拟析构函数并在 Value 中覆盖它。尽管如此,从 value_ 中删除引用也修复了我的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-08
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    相关资源
    最近更新 更多