垃圾收集的想法

发布于 2024-11-02 19:14:29 字数 252 浏览 5 评论 0原文

我正在开发一种使用 C++ 作为中间语言的玩具语言,目前它只支持三种类型,所有类型都来自基类:整数、列表和 lambda。所有函数都来回传递基类。编译后的代码在微控制器上运行,这意味着存在某些限制,我只有 8 kb 的 RAM,所以理想情况下,我想在使用完该对象后立即将其删除。另外,我无法访问大多数标准库(没有 Boost、STL 等...)。

所以我的问题是我应该如何解决这个问题?当我开始时,我虽然只使用共享指针,但事实证明,当将一堆整数添加到列表中时,这并不起作用。

I am working on a toy language that uses C++ as an intermediate language, currently it only supports three types all decent from a base class, integer, list and lambda. All functions pass base class back and forth. Compiled code runs on a microcontoller, which means there are certain restrictions I only have 8 kb of ram so ideally I want to get rid of the object as soon as I am done with it. Also I don't have access to most of the standart libs (no Boost, STL etc..).

So my question is how should i attack this problem? When I started I though I would just use shared pointers but that turns out does not really work say when a bunch of integers are added to a list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞别 2024-11-09 19:14:29

垃圾收集总是会产生内存和 CPU 开销,因此在微控制器上您应该避免它。您可能想要使用的是简单的、旧的引用计数。对于 Objective-C 来说效果很好,每个 iPhone/iPad/iPod Touch 应用程序和很多(大多数?)Mac 应用程序都使用它。你可以这样做:

你的对象基类有一个整数,即引用计数器。一旦对象被分配,计数器就会设置为 1。有一个方法 retain 可以增加计数器,还有一个方法 release 可以减少计数器。一旦 release 使计数器达到 0,就会调用解构函数并释放(释放)对象。

您必须小心避免保留循环,即像 A <-> 上那样相互保留的对象。 B或A-> B-> C-> A 因为这样引用计数器就不能降至 0,并且会出现内存泄漏。苹果通过命名和其他约定解决了这个问题(例如,如果一个对象有委托,则永远不会保留该委托)。

引用计数的优点在于它可能是保持内存尽可能低的最佳“垃圾收集”方法。它的内存和CPU 开销相当低。它的主要缺点是前面提到的引用循环是一个问题,并且您还需要在程序中显式保留/释放,因为语言无法猜测何时保留。

Garbage collection always has memory and CPU overhead, so on a microcontroller you should avoid it. What you might want to use is the simple, old reference counting. Works very well for Objective-C, every iPhone/iPad/iPod Touch app uses it and a lot (most ?) Mac applications. You do it like this:

Your object base class has an integer, the reference counter. Once an object gets allocated, the counter is set to 1. There's a method retain which increases the counter and a method release which decreases the counter. Once release makes the counter reach 0 the deconstructor is called and the object is deallocated (freed).

You have to be careful to avoid retain cycles, i.e. objects that retain each other as on A <-> B or A -> B -> C -> A as then the reference counter can't drop to 0 and you'd have a memory leak. Apple solves this through naming and other conventions (e.g. if an object has a delegate, the delegate is never retained).

The advantage of reference counting is that it probably is the best "garbage collection" method for keeping the memory as low as possible. It's memory and CPU overhead are fairly low. It's major disadvantage is that the previously mentioned reference cycles is a problem, and you also need to explicitly retain/release in your program as the language won't be able to guess when not to retain.

岁月静好 2024-11-09 19:14:29

我知道垃圾收集的两种通用机制:

  • 引用计数
  • 标记和清除

有各种风格/改进,它们更多地对应于实现策略(分代,复制,压缩,...)。

一般来说,引用计数对于反应性来说是最好的(这在这里很重要),但是存在引用循环的问题(取决于您的玩具语言语义)。

有复杂的算法来处理周期的收集,但更简单的解决方案是:

  • 使用引用计数进行在线维护
  • 每当内存达到定义的阈值时,执行完整的“标记和清除”收集以收集泄漏的周期

I know of two general mechanisms for garbage collection:

  • Reference Counting
  • Mark And Sweep

There are various flavors / improvements which correspond more to implementations strategies (Generational, Copying, Compacting, ...).

In general, the Reference Counting is the best for reactivity (which is important here), however there is the issue of reference cycles (depending on your toy language semantics).

There are complicated algorithms to deal with the collection of cycle, but the simpler solution is:

  • Use Reference Counting for on-line maintenance
  • Perform a full "Mark-And-Sweep" collection whenever the memory reaches a defined treshold to collect the leaked cycles
三生路 2024-11-09 19:14:29

其他人提到了引用计数及其循环依赖的问题。如果您想使用引用计数(如上所述,它快速且响应迅速),避免循环问题的一种方法是在所有地方使用值语义。如果您在用户级别没有指针/引用,那么您不必担心这些循环依赖关系。

为了节省内存,您可能需要使用一些写时复制语义。即:

x = list('a','b','c','d')
y = x; 
// x and y point to the same list in memory
y.replace(2, 'e') 
// x and y point to different lists in memory
// those 2 lists share instances of 'a', 'b', and 'd'

如果您不使用诸如写时复制之类的东西,则内存使用量可能会因值语义而激增。

Others have mentioned reference counting and it's problems with cyclic dependencies. If you want to go with reference counting (which is fast and responsive, as mentioned), one way to avoid the cyclic problem is to use value semantics in all places. If you don't have pointers/references at the user level, then you don't have to worry about those cyclic dependencies.

It order to conserve on memory, you'd probably want to work with some copy-on-write semantics. Ie:

x = list('a','b','c','d')
y = x; 
// x and y point to the same list in memory
y.replace(2, 'e') 
// x and y point to different lists in memory
// those 2 lists share instances of 'a', 'b', and 'd'

If you don't use something like copy-on-write, the memory use can shoot up from the value semantics.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文