【发布时间】:2012-02-04 13:28:44
【问题描述】:
如何让 Mono 中的垃圾收集器做任何有用的事情?这篇文章的底部是一个简单的 C# 测试程序,它生成两个大字符串。生成第一个字符串后,解引用变量,退出作用域,手动触发垃圾收集器。尽管如此,使用的内存并没有减少,并且程序在构造第二个字符串期间因内存不足异常而爆炸。
未处理的异常:OutOfMemoryException [ERROR] FATAL UNHANDLED 异常:System.OutOfMemoryException:内存不足(包装 托管到本机)字符串:InternalAllocateStr (int) at System.String.Concat (System.String str0, System.String str1) [0x00000] in :0 at GCtest.Main (System.String[] args) [0x00000] in :0
经过研究,我发现 Mono 的 --gc=sgen 开关使用不同的垃圾收集算法。更糟糕的是,会生成以下堆栈跟踪:
堆栈跟踪:
at (wrapper managed-to-native) string.InternalAllocateStr (int) at string.Concat (string,string) at GCtest.Main (string[]) at (wrapper runtime-invoke) .runtime_invoke_void_object(对象,intptr,intptr,intptr)
本机堆栈跟踪:
0 单基因 0x000bc086 mono_handle_native_sigsegv + 422 1 单声道
0x0000466e mono_sigsegv_signal_handler + 334 2 libsystem_c.dylib
0x913c659b _sigtramp + 43 3 ???
0xffffffff 0x0 + 4294967295 4 单发电机
0x0020306d mono_gc_alloc_obj_nolock + 363 5 mono-sgen
0x0020394a mono_gc_alloc_string + 153 6 mono-sgen
0x001c9a10 mono_string_new_size + 147 7 单声道
0x0022a6d1 ves_icall_System_String_InternalAllocateStr + 28 8 ???
0x004c450c 0x0 + 4998412 9 ???
0x004ceec4 0x0 + 5041860 10 ???
0x004c0f74 0x0 + 4984692 11 ???
0x004c1163 0x0 + 4985187 12 单基因
0x00010164 mono_jit_runtime_invoke + 164 13 mono-sgen
0x001c5791 mono_runtime_invoke + 137 14 mono-sgen
0x001c7f92 mono_runtime_exec_main + 669 15 mono-sgen
0x001c72cc mono_runtime_run_main + 843 16 单声道
0x0008c617 mono_main + 8551 17 mono-sgen
0x00002606 开始 + 54 18 ???
0x00000003 0x0 + 3来自 gdb 的调试信息:
/tmp/mono-gdb-commands.2aCwlD:1:源命令文件中的错误:无法 自我调试
在执行本机代码时获得了 SIGSEGV。这通常表示致命 单声道运行时或您使用的本机库之一中的错误 应用。
/Users/fraser/Documents/diff-match-patch/csharp/GCtest.command: 行 12:41011 中止陷阱:6 单声道--gc=sgen GCtest.exe
代码如下:
using System;
public class GCtest {
public static void Main(string[] args) {
Console.WriteLine("Memory: " + (GC.GetTotalMemory(true) / 1024) + " KB");
{
// Generate the first string.
string text1 = "hello old world.";
for (int i = 0; i < 25; i++) {
text1 = text1 + text1;
}
// Dereference variable.
text1 = null;
// Drop out of scope.
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Memory: " + (GC.GetTotalMemory(true) / 1024) + " KB");
// Generate the second string.
string text2 = "HELLO NEW WORLD!";
for (int i = 0; i < 25; i++) {
text2 = text2 + text2;
}
Console.WriteLine("Memory: " + (GC.GetTotalMemory(true) / 1024) + " KB");
}
}
【问题讨论】:
-
奇怪地使用了“dereference”这个词。取消引用是跟随指向其目的地的指针的过程。我会说“将 null 分配给变量”。
标签: c# mono garbage-collection