我正在尝试将一些绑定写入Boehm GC for Rust.
一些背景:Rust被设计为高并发语言,这种设计的结果是能够将GC指针静态地限制在分配它们的线程内(也就是说,在线程x中分配的GC指针可以永远不会被另一个线程保持活着(甚至完全被引用).
因此,我希望驾驶Boehm尽可能地利用它来获得性能:
1很简单,但我找不到2和3的任何工具.最重要的部分是1和2因为我希望能够在后台运行线程,而不管其他线程在做什么(即使它们都是分配和垃圾收集千兆字节的内存).
(我确实知道THREAD_LOCAL_ALLOC&gc_thread_local.h,但是这并不完全满足3,它只是使它更有效,但它仍然有效传递线程之间本地线程分配的指针,而我不需要保证.)
我认为两者(分代和增量)是使垃圾收集暂停更快的不同方法.但是世代和增量之间有什么区别?他们是如何工作的?哪一个更适合实时软件/产生较少的长时间停顿?
此外,Boehm GC是其中之一吗?
该贝姆保守的垃圾收集器的(如相当有用中的bigloo时,用它狡诈使用类似的东西,等...),尤其是在Linux操作系统(这是我关心的只是OS;我使用Debian/SID/86 -64如果重要,并且libgc-dev包是版本,1:7.4.2-8那么Boehm GC是7.4.2).
但是,Boehm的GC需要知道使用它的每个线程.它的gc_pthreads_redirects.h(或多或少内部)头文件正在重新定义pthread_create为
# define pthread_create GC_pthread_create
Run Code Online (Sandbox Code Playgroud)
实际上,Boehm的GC需要的是GC_register_my_thread在新的线程调用堆栈中提前调用(并且GC_pthread_create正在这样做).
在过去,Glib(2.46)提供了一种重新定义内存分配的方法,使用struct GMemVTable该方法已 被弃用且不能再使用(我的Debian libglib2.02.0-dev软件包是版本2.50.3-2).有一个g_mem_gc_friendly全局布尔值,但在查看Glib源代码时,它只是在释放它们之前清除内存区域.
最近的GTK3(我的libgtk-3-dev 软件包有版本3.22.11-1)正在使用(间接)pthread_create通过Glib线程函数创建线程(可能与Dbus相关,也可能与GtkTextView相关...).除了通过修补源代码之外,没有办法通知该线程创建.我害怕比我g_signal_connect可以从这些线程调用的任何GTK回调(例如使用).或者,如果我使用某些可能使用(或访问)某些GC_malloc-ed缓冲区的方法对GTK小部件进行子类化,则可能会发生灾难.
另一方面,GTK中有一个强大的编码规则,所有GTK操作都应该只在主线程中发生.引用Gdk3线程页面:
GTK +,但是,是不是线程安全的.您应该只使用GTK +和GDK从线程
gtk_init()和gtk_main()被称为上.这通常被称为"主线程".
如果我自己遵循这个规则,我确信没有内部GTK代码可以从一些非主线程调用我的回调(使用Boehm GC)?
我的直觉是,如果GC_alloc …
我检查了Boehm GC.用于C/C++的GC.
我知道标记和扫描算法.我很好奇的是它如何只在整个C内存中获取指针.我对C内存的理解只是一个普通的字节数组.是否有可能确定内存中的值是否为指针?
我在Mono的网页上看到他们在精确模式下使用Boehm GC.我也使用Boehm GC与C++,但是,我在其文档或标题中没有发现任何表明精确模式的内容,更不用说如何打开它.
是否有任何信息默认情况下它实际上是否具有精确模式以及如何打开它,或者它只是Mono开发人员的某种修改?
在我再次关闭的编译器项目中,我已经将闭包实现为具有可执行前缀的已分配内存.所以闭包是这样分配的:
c = make_closure(code_ptr, env_size, env_data);
Run Code Online (Sandbox Code Playgroud)
c 指向已分配内存块的指针,如下所示:
movl $closure_call, %eax
call *%eax
.align 4
; size of environment
; environment data
; pointer to closure code
Run Code Online (Sandbox Code Playgroud)
closure_call是一个辅助函数,它查看最近放在堆栈上的地址,并使用它来查找闭包数据和代码指针.Boehm GC用于一般内存管理,当不再引用闭包时,它可以由GC解除分配.
无论如何,这个分配的内存需要标记为可执行; 事实上,它跨越的整个页面都被标记出来.随着闭包的创建和释放,进程中越来越多的堆内存将是可执行的.
出于防御性编程的原因,我宁愿最小化可执行堆的数量.我的计划是尝试将所有闭包保存在同一页面上,并根据需要分配和释放可执行页面; 即为闭包实现自定义分配器.(如果所有闭包大小相同,这会更容易;因此第一步是将环境数据移动到可以正常管理的单独的非可执行分配中.这也使得防御性编程有意义.)
但剩下的问题是GC.Boehm已经做到了!我想要的是以某种方式告诉Boehm关于我的自定义分配,并让Boehm告诉我他们什么时候能够进行GC,但要让我自己解除分配.
所以我的问题是,Boehm中是否有钩子提供这样的自定义分配?
我正在尝试在C中实现一个简单的标记和清除垃圾收集器.算法的第一步是找到根.所以我的问题是如何在C程序中找到根源?
在使用malloc的程序中,我将使用自定义分配器.这个自定义分配器是从C程序调用的所有东西,也可以是自定义的init().
垃圾收集器如何知道程序中的所有指针(根)?另外,给定一个自定义类型的指针,它如何得到所有指针?
例如,如果有一个指向类列表的指针p,其中有另一个指针...说q.垃圾收集器如何知道它,以便它可以标记它?
更新:如果我在启动它时将所有指针名称和类型发送到GC怎么样?类似地,也可以发送不同类型的结构,以便GC可以遍历树.这甚至是一个理智的想法还是我只是疯了?
我在LinuxJournal上读过有关Boehm-Demers-Weiser垃圾收集器库的文章.我很有兴趣在我的库中使用它而不是我自己的引用计数实现.
我只有一个问题:是否可以仅将gc用于我的共享库,并且仍然在主应用程序中使用malloc/free?我不太明白gc如何检查堆,所以我担心在这种情况下gc的性能和可能的副作用.
我正在尝试将Boehm垃圾收集器与GLib集成在Linux中,但在一种情况下,我发现它并没有释放内存:当我多次调用g_strsplit时,它会耗尽内存和段错误.垃圾收集器的README警告它可能无法在动态库中查找指针,并且可能需要使用GC_add_roots.
为了测试这一点,我将GLib中的所有相关代码复制到我的源文件中,而不是根据libglib-2.0.so进行链接.这消除了段错误,这告诉我这确实是问题所在.但是,没有关于如何使用GC_add_roots来解决此问题的文档.有人能帮我吗?
以下是导致内存泄漏的代码:
#include <glib.h>
#include <gc.h>
void no_free(void *mem) {}
int main() {
g_mem_gc_friendly = TRUE;
GMemVTable memvtable = {
.malloc = GC_malloc,
.realloc = GC_realloc,
.free = no_free,
.calloc = NULL,
.try_malloc = NULL,
.try_realloc = NULL
};
g_mem_set_vtable(&memvtable);
for (int i = 0; i < 10000; i++) {
char **argv = g_strsplit("blah", " ", 0);
argv[0][0] = 'a'; // avoid unused variable warning
}
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试将一些函数从 glib 绑定到 Crystal 中。我已经这样做了并且有效:
@[Link("glib-2.0")]
lib LibG
fun g_utf8_strup(str : UInt8*, len : UInt32) : UInt8*
fun g_utf8_strdown(str : UInt8*, len : UInt32) : UInt8*
end
Run Code Online (Sandbox Code Playgroud)
然而它引入了内存泄漏:使用 g_* 函数创建的对象永远不会被垃圾收集。
是否有可能让glib在Crystal中与Boehm GC一起很好地发挥作用?受PCRE的启发,我尝试过:
@[Link("glib-2.0")]
lib LibG
# These 2 functions work perfectly
fun g_utf8_strup(str : UInt8*, len : UInt32) : UInt8*
fun g_utf8_strdown(str : UInt8*, len : UInt32) : UInt8*
alias Malloc = LibC::SizeT -> Void*
alias Free = Void* ->
$g_malloc : Malloc
$g_free : Free
end
# …Run Code Online (Sandbox Code Playgroud) 我偶然发现了这个问题:ContentView中的按钮导致MonoTouch运行时崩溃.Monotouch 4.0中的错误?而询问者对Monotouch的"更具侵略性"的垃圾收集器存在问题.
也许其中一个Xamarin团队可以总结一些注意事项并给出一个很好的解释?
我目前正在从MT 3.2.6升级到MT 4.1,并希望查看我的代码并检查需要更改的内容.
运行我的程序时,我从Boehm GC中获得以下错误(定义了GC_DEBUG):
GC_check_heap_block: found smashed heap objects:
0x8ef1008 in or near object at 0x8ef1010(<smashed>, appr. sz = 29)
0x8ef1188 in or near object at 0x8ef1190(<smashed>, appr. sz = 29)
...
Run Code Online (Sandbox Code Playgroud)
以上持续约20次.
奇怪的是,我找不到程序的任何问题,它做了它应该做的事情,并且没有崩溃.
我可以编译我的程序来禁用GC.然后我可以用它运行valgrind,但奇怪的是,valgrind没有发现任何问题!
这可能是Boehm GC中的一个问题 - 我应该忽略它吗?
有没有人有任何想法如何有效地调试这个?
或者,任何人都能解释上述消息的确切含义吗?
boehm-gc ×12
c ×7
c++ ×2
glib ×2
.net ×1
closures ×1
concurrency ×1
crystal-lang ×1
gc-roots ×1
gtk ×1
linux ×1
memory-leaks ×1
mono ×1
principles ×1
rust ×1
valgrind ×1
xamarin.ios ×1