【问题标题】:Why cannot structs storing plain pointers to internal memory be stored in stxxl containers?为什么存储指向内部内存的普通指针的结构不能存储在 stxxl 容器中?
【发布时间】:2014-02-24 14:22:45
【问题描述】:

stxxl 常见问题解答中,我发现了这个:

参数化 STXXL 容器

像 stxxl::vector 这样的 STXXL 容器类型只能参数化 具有 POD 的值类型(即没有虚函数,没有 用户定义的拷贝赋值/析构函数等)并且不包含 对内部内存的引用(包括指针)。通常,“复杂” 数据类型不满足此要求。

这就是为什么stxxl::vector<std::vector<T> >stxxl::vector<stxxl::vector<T> > 无效。如果合适,使用 std::vector<stxxl::vector<T> >,或通过以下方式模拟二维数组 做指数计算。

无法使用stxxl::vector<std::vector<T> > 非常有意义,因为stxxl 容器不会在容器调整大小时调用所包含元素的构造函数或析构函数。但是如何存储这样的结构:

struct S {
    int* a;
}

如果我确实保证a 指向的对象只要存在stxxl::vector<S> 实例就有效,那么将这个struct 存储到stxxl::vector<S> 中有什么问题?如果必须将S 的特定实例移动到磁盘,则将a 指针的值写入磁盘。稍后,指针值被恢复,我可以使用它。显然,指针值也依赖于机器和实例,但这是一个问题即使我照顾了指向对象的生命周期吗?我没有通过套接字发送序列化对象,也没有将序列化对象存储在数据库中以供以后使用。

我错过了什么吗?

编辑:有人提醒我stxxl 不会复制指针,因此当我稍后检索struct S 的实例时,我可能会得到一个指向垃圾的指针。我知道。我保证指针在程序的整个生命周期内都是有效的。

【问题讨论】:

  • 我的猜测是数据存储在这些指针有意义的虚拟内存地址空间之外的某个地方。
  • 在这种情况下,这些指针在复制回它们“出生”的上下文时再次有意义。指针不只是一个整数吗?请注意struct S不关心*a指向的对象的创建/销毁
  • 容器必须针对值语义进行设计,就像它们的标准库对应物一样。所以任何指向内部数据的指针都必须指向容器自己管理的内存,而不是一些外部实体。
  • 我对 STXXL 的了解不够(否则我会尝试回答这个问题),但我想如果你存储一个指针,它会保留它的值,你可以在以后取消引用它,只要它指向一个有效的对象。如果它做了其他事情,我会感到惊讶。
  • 我认为(不熟悉这个库)这只是一个文档问题:他们试图让初学者很难错过这个限制,而不涉及有效高级使用的细节。跨度>

标签: c++ pointers vector stxxl


【解决方案1】:

(包括指针)到内部存储器

这意味着指向结构成员的指针,或者指向容器管理的内存的指针。例如。你有

struct Foo {
     int *a;
     int b;
};

Foo f;
f.a = &f.b

由于f.a 现在指向结构的成员,并且可以复制该结构,因此指针可能无效。类似地,如果指针指向由容器管理的任何其他结构 Foo - 也可以移动。

如果你只有一个指针,并管理它指向的东西,你应该没问题。

【讨论】:

  • 谢谢,不。我认为 internal memory 只是表示 main memory,因为库作者通常将 external memory 称为非主存(即磁盘) .那么我做了一个错误的假设。
  • 在这些上下文中使用术语内部存储器是正常的。 +1
【解决方案2】:

在具有严格指针安全性的实现中,您保存了指向磁盘的指针这一事实是不够的。如果该指针不再在内存中,则它指向的对象不再有效 - 即使您从磁盘恢复指针位也是如此。特别是,它可能在没有运行任何 dtor 的情况下被垃圾收集。

【讨论】:

  • 这很有趣,你能详细说明一下吗?有没有像你说的那样表现的现实世界的实现?
  • 使用 Boehm GC 运行将是一个明显的现实示例。
【解决方案3】:

我想这是因为容器中的数据是使用 memcpy 类型的方法复制进来的——所以如果你的类中有一个要存储的指针,你会复制指针而不是指向的数据.

当你序列化这样的结构时,指向的数据不会被序列化,只有指针。当您恢复数据时,您将拥有一个指向垃圾的指针。

【讨论】:

  • 复制指针——而不是指针——正是我想要做的。指针是否指向垃圾应该是我的事。我可以向你保证,我会以我的生命为代价保护*a指向的对象。那么有什么问题呢?
  • @gd1 然后继续忽略他们的建议,把你的指针放在那里看看会发生什么。当然,您需要对此发表评论,以免其他人误解这种非典型行为。
  • 重点不在于我在做什么或我将要做什么。如果他们建议在基于他们的库编写代码的同时唱歌,我会这样做。尽管如此,我还是喜欢了解事物为什么的人之一。如果你知道原因,请贡献。否则,将问题悬而未决完全没有问题,可以节省我们双方的大量时间。
  • @gd1 我告诉你原因。在学习 C 时,指针和它的数据不是一回事,这是初学者的错误。这个图书馆告诉你同样的事情,但以一种迂回的方式。这也是为什么他们说也不使用复杂类型的原因。调试到他们的复制构造函数,你会看到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
相关资源
最近更新 更多