在操作过程中发生内存不足时,撤消C动态数据结构中的更改

问题描述 投票:3回答:2

我在C中实现了一些支持各种操作的复杂数据结构。此数据结构使用许多其他动态结构(图形,AVL树,链接列表),一切都使用动态内存。

在进行某些操作时,例如插入到我的数据结构中,显然我必须分配内存,有时很多(因此结构增长)。这可能导致内存不足(malloc()返回NULL)在执行某些操作的过程中。现在,我不想终止我的程序,但让操作的调用者知道操作失败并让调用者继续执行。

我的问题是,当由于内存分配失败而在执行过程中操作失败时,我想撤消自调用操作以来所执行的操作,撤消数据结构中的这些更改,以便从未调用此操作(所以在执行操作之前将数据结构恢复到正确的状态)。我需要这个,因为即使操作失败,我希望我的数据结构处于有效和可用的状态,所以我可以继续使用它。

由于数据结构非常先进,我正在寻找关于在调用操作之前将动态数据结构恢复到其状态的一般方法,提示和技巧。也许你有一些处理这些问题的经验,听说过这个问题,或者可以建议一些有关它的书籍/文章或相关的源代码。

编辑:一个简单的例子将从C ++设置<>。根据STL文档,即使抛出异常,set :: insert也能很好地工作,所以它能够以某种方式恢复在set :: insert执行期间所做的更改,即使set的基础数据结构(可能是红黑树)非常先进。

引自cplusplus.com:“如果要插入单个元素,则在异常情况下(强保证)容器中没有变化。否则,容器将保证以有效状态结束(基本保证)。”

c algorithm memory-management data-structures out-of-memory
2个回答
5
投票

处理此类情况的常用方法是首先进行干运行并分配整个操作所需的内存。实际上只有在所有分配成功时才进行更新。

当然,这可能并不总是可行的,因为您可能必须调用其他没有“空运行”模式的操作,或者在您实际执行操作之前可能不会显示某些分配。对于这种情况,复制数据结构通常是最佳选择。同样,由于复制是只读操作,因此很容易中止和反转。

用户可能希望避免重复和跟踪额外数据结构或进行干运行的开销。因此,此功能可以作为可选功能(可能使用#ifdef),用户可以选择反转操作或终止整个程序。


1
投票

在C ++中,一种常见的方法是以“临时”的形式构造结果,然后交换临时和结果。您可能还会执行在交换后无法失败的其他更改。

您可以查看What is the copy-and-swap idiom?的灵感 - 即使这是交换的特定用途,您可能不需要复制部分。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.