我还没有完全理解段错误和回溯是如何工作的,但我的印象是,如果列表顶部的函数引用“glib”或“gobject”,那么通常应该会出现错误问题(TM)不要出错。
嗯,这就是我从两个完全不同的程序中得到的结果。
第一个是 irssi 的最新版本,直接从 github.com 编译(干净,没有任何故障或错误)。
Program received signal SIGSEGV, Segmentation fault.
0xb7cf77ea in g_ascii_strcasecmp () from /usr/lib/libglib-2.0.so.0
(gdb) bt
#0 0xb7cf77ea in g_ascii_strcasecmp () from /usr/lib/libglib-2.0.so.0
#1 0x08103455 in config_node_section_index ()
#2 0x081036b0 in config_node_traverse ()
#3 0x080fb674 in settings_get_bool ()
#4 0x08090bce in command_history_init ()
#5 0x08093d81 in fe_common_core_init ()
#6 0x0805a60d in main ()
我遇到问题的第二个程序是 NetSurf Web 浏览器(它也可以 100% 干净地编译),当它针对 GTK 构建时(当不是为使用 GTK 构建时,它运行良好):
Program received signal SIGSEGV, Segmentation fault.
0xb7c1bace in g_type_check_instance_cast () from /usr/lib/libgobject-2.0.so.0
(gdb) bt
#0 0xb7c1bace in g_type_check_instance_cast () from /usr/lib/libgobject-2.0.so.0
#1 0x080cd31c in nsgtk_scaffolding_set_websearch ()
#2 0x080d05da in nsgtk_new_scaffolding ()
#3 0x080dafd8 in gui_create_browser_window ()
#4 0x0809e806 in browser_window_create ()
#5 0x080c2fa9 in ?? ()
#6 0x0807c09d in main ()
我 99.99% 确信我正在查看的问题是 glib2 的某种故障。我的系统的其余部分工作 100% 正常,只是这两个程序在做奇怪的事情。
我同样相信,如果我尝试构建使用这些库的其他程序,它们也很可能会失败。
显然,戳戳油嘴滑舌和朋友们——甚至犯一个微小的错误——是让系统中几乎每个程序都灾难性地崩溃的一个即时秘诀(我是根据很久以前在另一个系统上的经验来说话的:P)。
鉴于我完全不知道自己在用这种东西做什么,而且我知道,所以我不愿意去那里;我想保持当前的系统配置正常运行:)
我正在考虑编译一个新的glib2(和 co.)的版本,然后将这些程序静态链接到它。我只是不知道该怎么做 - 我需要执行哪些步骤?
我的另一个想法是将./configure --prefix=/usr; make; make install
我现在拥有的完全相同版本的 glib“放回到”我的系统中,重新安装它。我看到相关的核心库都以“0.3200.4”:
-rwxr-xr-x 1 root root 1.4M Aug 9 2012 /usr/lib/libgio-2.0.so.0.3200.4
-rwxr-xr-x 1 root root 1.2M Aug 9 2012 /usr/lib/libglib-2.0.so.0.3200.4
-rwxr-xr-x 1 root root 11K Aug 9 2012 /usr/lib/libgmodule-2.0.so.0.3200.4
-rwxr-xr-x 1 root root 308K Aug 9 2012 /usr/lib/libgobject-2.0.so.0.3200.4
-rwxr-xr-x 1 root root 3.7K Aug 9 2012 /usr/lib/libgthread-2.0.so.0.3200.4
这可能会起作用,或者会严重破坏事情吗? :S
如果它可能有效,“0.3200.4”会翻译成什么版本?
我还可以尝试哪些其他想法?
我不一定要寻找 glib 本身的修复来纠正正在发生的任何基本错误 - 它不会影响我那很糟糕。我只是想让 irssi 和 NetSurf 正确运行。
答案1
我的印象是,如果列表顶部的函数引用“glib”或“gobject”,则通常不会出错的库会出现 Bad Issues(TM)。
如果您的意思是这表明缺陷可能存在于这些库中,那么您会得到错误的印象。这并不是这个意思;更有可能的是,这就是之前的错误最终爆发的地方。从本质上讲,C 中没有很多运行时保护措施,因此您可以轻松传递将编译但不会进一步验证的参数(除非您自己这样做)。简单的例子:
int main (void) {
char whoops[3] = { 'a', 'b', 'c' };
if (strcmp(whoops, "abcdef")) puts(whoops);
将未终止的字符串传递给多个不同的字符串函数。这将编译没有问题,并且很可能运行正常,因为内存违规会非常轻微,但是可以strcmp()
或中的段错误puts()
。这并不意味着strcmp()
实现有问题;而是意味着实现有问题。错误显然就在那里main()
。
像这样的函数无法从逻辑上确定传递的参数是否正确终止(这就是我的意思是 WRT 运行时检查,而 C“本质上”缺乏它们)。规定编译器应该检查并没有多大意义,因为大多数时候数据不会像那样被硬编码。
回溯中间的东西也不一定起作用,尽管它可以。一般来说,开始寻找的地方是最后的入口;这就是问题所在追溯到。
但错误可能总是存在于任何地方。通常将回溯与内存检查器报告的错误进行比较valgrind
可以帮助缩小范围。 WRT 你的例子可能有很多需要筛选的地方;最后我检查了 valgrind 和 gtk 不是快乐的玩伴。
我正在考虑编译新版本的 glib2(和 co.),然后将这些程序静态链接到它。
你可以,尽管我看不出有任何理由相信任何事情都会因此而变得更好。它正在抓住救命稻草。您实际上无法自己调试问题,这是可以理解的,因此您在绝望中考虑可以尝试什么。
最有可能的是,你只会浪费大量时间并使自己感到沮丧。
我 99.99% 确信我正在查看的问题是 glib2 的某种故障。
我99%相信你在这方面过于自信了。
又是bug可以根据经验,无论在任何地方,都应将经过最广泛测试的部件视为最不可能的罪魁祸首。在这种情况下,glib 相当普遍,而 irssi 和 NetSurf 则相对晦涩难懂。
对您来说最好的办法可能就是提交错误报告。回溯通常在那里很受欢迎。从 irssi 和 NetSurf 开始;如果你直接说油嘴滑舌,他们会合理地说,他们没有理由相信这是他们的问题,除非你能证明这一点(这一切都不能证明)。另一方面,如果 irsi 人决定了是在油嘴滑舌的情况下,他们可能会想自己去追求这一点。