5

对标题问题的进一步解释是有序的,让我解释一下我的场景。

我有一个指向堆上几个对象的指针的列表容器。每当创建一个新对象时,就会将指向它的指针添加到列表中,而每当删除一个对象时,它的指针就会被删除。可以肯定地说,此列表上的所有指针始终有效。

列表中的许多对象都包含指向同一列表中其他对象的指针。

在我取消引用这些指针中的任何一个之前,我想使用一个CheckAgainstList(ptr*)函数来确保一个对象指向同一个列表中的另一个对象,因此没有指向一个已经被删除的对象。

现在戴上你的锡纸帽子,这可能吗?

  1. 对象 A 有一个指向对象 B 的指针,其内存地址为 0x00988e50
  2. 对象 B 被删除。
  3. 对象 C 被创建并被放置到新释放的内存空间0x00988e50中。
  4. CheckAgainstList(ptr*)当我们检查指针时返回 true,因为对象 C 在列表中并且与 B 曾经占用的内存地址相同。

现在我们有一个错误,因为 A 认为它有一个指向 B 的指针,但是 B 消失了,可以说是 C 取而代之。

这个潜在的错误甚至可能吗?

4

5 回答 5

6

不仅有可能,而且很有可能。一个好的内存分配器会尝试尽可能频繁地重用内存,以减少碎片和膨胀。

您尝试解决的问题可能适用于weak_ptr,可以在使用之前检查其有效性。

于 2012-06-22T18:04:02.640 回答
4

是的,这个错误是完全可能的。

基本上你正在做的事情是非常危险的,并且会很快导致错误。您最好使用某种引用计数的智能指针。C++11 包含 std::shared_ptr ,这意味着您可以使用它来代替普通指针。这样,在一切都完成之前,内存不会被释放,并且会缓解您所描述的问题。

您唯一的其他选择是扫描所有其他对象以查看它们是否引用已删除的“B”并执行“null”之类的操作,使其指向现已删除的指针。

于 2012-06-22T18:01:39.480 回答
4

内存地址确实会被重用 - 取决于操作系统。否则,如果一个程序进行了大量的分配和释放,超过了机器中的 RAM,它将无法继续。

最后,答案更多的是关于操作系统及其内存管理方案,而不是 C++ 本身。毕竟,当您分配自由存储(动态)内存时,最原始的情况是进程(通过标准库函数)调用特定的操作系统例程来分配请求的内存量并将地址返回给分配的内存。

于 2012-06-22T18:02:35.507 回答
1

如果您只创建一种类型的对象,则更有可能出现该错误。但这总是完全可能的。

于 2012-06-22T18:03:58.567 回答
0

是的,这可能发生。为了防止这种情况,当您删除一个对象时,请遍历列表并将任何指向已删除对象的指针设置为指向 NULL。

于 2012-06-22T18:04:48.503 回答