Ofe*_*Ron 7 c concurrency garbage-collection memory-management
在这里阅读它.
我需要实现这样一个接口的变体,比如说我们有一个大的内存空间来管理应该有getmem(大小)和free(指向块的指针)函数,必须确保free(指向block的指针)实际上可以释放当且仅当使用该块的所有进程都使用它完成时的内存.
我正在考虑做的是将Collectable
结构定义为块的指针,它的大小和使用它的进程计数.然后,每当第一次使用Collectable
struct实例的进程必须显式递增计数时,每当进程执行free()
时,计数就会递减.
这种方法的问题是所有进程都必须响应该接口并使其显式工作:每当为实例分配可收集指针时,进程必须明确地包含该计数器,这不满足我,我想也许有办法创建一个宏,以便在每个任务中隐式发生?
我正在寻找解决这个问题的方法,所以其他的方法和想法会很棒......
编辑:上面的方法不满足我不仅因为它看起来不漂亮,而且主要是因为我不能假设正在运行的进程的代码会关心更新我的计数.我需要一种方法来确保完成它而不改变进程的代码......
引用计数的一个早期问题是,通过将代码放入自定义 malloc/free 实现中来计算初始引用相对容易,但要确定初始接收者是否将该地址传递给其他人则相当困难。
由于 C 缺乏覆盖赋值运算符(计算新引用)的能力,因此基本上您只能选择有限数量的选项。唯一可能覆盖赋值的是macrodef,因为它能够将赋值重写为内联引用计数值增量的内容。
所以你需要“扩展”一个看起来像的宏
a = b;
Run Code Online (Sandbox Code Playgroud)
进入
if (b is a pointer) { // this might be optional, if lookupReference does this work
struct ref_record* ref_r = lookupReference(b);
if (ref_r) {
ref_r->count++;
} else {
// error
}
}
a = b;
Run Code Online (Sandbox Code Playgroud)
真正的技巧是编写一个可以识别赋值的宏,并干净地插入代码而不会引入其他不需要的副作用。由于 macrodef 不是一种完整的语言,您可能会遇到无法匹配的问题。
(关于在学习如何使用锤子的地方看到钉子的笑话在这里有一个有趣的相似之处,除了当你只有一把锤子时,你最好学会如何把所有东西都变成钉子)。
其他选项(也许更理智,也许不是)是跟踪 malloc 分配的所有地址值,然后扫描程序的堆栈和堆以查找匹配的地址。如果匹配,您可能找到了一个有效的指针,或者您可能找到了一个带有幸运编码的字符串;但是,如果不匹配,当然可以释放地址;如果他们不存储从原始地址计算的地址 + 偏移量。(也许你可以用宏定义来检测这样的偏移量,并将偏移量添加为同一块扫描中的多个地址)
最后,如果不构建一个引用系统,您将返回引用(假装地址),就不会有万无一失的解决方案;隐藏真实地址。这种解决方案的缺点是每次要处理地址时都必须使用库接口。这包括数组中的“下一个”元素等。不是很像 C,但非常接近 Java 对其引用所做的工作。
半严肃的回答
#include "Python.h"
Run Code Online (Sandbox Code Playgroud)
Python 有一个很棒的引用计数内存管理器。如果我必须在生产代码中真正做到这一点,而不是家庭作业,我会考虑将 python 对象系统嵌入到我的 C 程序中,这将使我的 C 程序也可以在 python 中编写脚本。如果您有兴趣,请参阅Python C API 文档!