【发布时间】:2017-03-09 14:40:12
【问题描述】:
就上下文而言,我对编程并不陌生,但对 unix 和 GTK 很陌生,所以这可能很简单,但我处于头撞模式。
我已经成功地从源代码构建了 MuPDF,包括运行的独立示例。
我刚开始学习从 C 调用 GTK3 并且有一个最简单的示例可以运行,当时我决定尝试将两者结合起来。长话短说 - 修剪后,我发现我在运行时遇到分段错误,当与 MuPDF 相关的某些代码行被编译和链接时,即使没有被调用。代码应该足够短,我希望:
main.c
#include <gtk/gtk.h>
#include "MuPDF_calls.h"
static void activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("com.leferguson.musicalpi", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
请注意,除了标题之外,这几乎完全来自 GTK+ 教程,除了放置一个窗口和按钮之外什么也不做。它实际上并没有调用接下来的例程:
完整性头文件:MuPDF_calls.h
#ifndef MUPDF_CALLS_H_
#define MUPDF_CALLS_H_
extern int getApage();
#endif /* MUPDF_CALLS_H_ */
还有 MuPDF_calls.c
#include <mupdf/fitz.h>
extern int getApage()
{
// Notice that this routine is not actually called by the main program
fz_context *ctx;
/* Create a context to hold the exception stack and various caches. */
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot create mupdf context\n");
return EXIT_FAILURE;
}
// If the section below this up to the closing brace before the last return is removed, the program works
// With this included, it gets a terminated, exit value -1, segmentation fault in do_scavenging_malloc()
fz_try(ctx)
fz_register_document_handlers(ctx);
fz_catch(ctx)
{
fprintf(stderr, "cannot register document handlers: %s\n", fz_caught_message(ctx));
fz_drop_context(ctx);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
这个例程基本上是来自 MuPDF 源代码的 example.c 的第一部分,为了简洁起见,这里删除了大部分代码,以便留下足以显示失败的内容。
最后这些是用以下命令构建的:
gcc -g `pkg-config --cflags gtk+-3.0` -c main.c -o build/main.o
gcc -g -I/home/ferguson/git/mupdf/include -c MuPDF_calls.c -o build/MuPDF_calls.o
gcc -g build/main.o `pkg-config --libs gtk+-3.0` build/MuPDF_calls.o -L/home/ferguson/git/mupdf/build/release -lmupdf -lmupdfthird -lm -lc -lgcc -lssl -lcrypto -o build/TestGTK
显然,如果您尝试重新创建它,请根据需要调整路径。我不建议这是漂亮或完整的,它是一个精简的版本,试图获得最低限度的失败。
再次,请注意名称丑陋的 getApage 例程实际上并未在 main() 中调用。但是,如果我使用源代码中包含的最后一个 try/catch 部分来构建(并链接它),程序会在运行时在 GTK 例程的某处给出分段错误(不显示窗口)。
如果我注释掉指示的行并且不进行其他更改并运行,它会按预期显示一个窗口。如果我在调试中运行它并在代码中设置中断,我不打算调用它不会到达它(因为它不应该)。
我将程序分开并使用不同的包含路径进行编译只是为了确保没有可能发生冲突的无关定义,这没有区别。
我已经在相关代码中扩展了宏,但没有任何反应(它在语法上是正确的,如果我使用扩展代码而不是宏进行编译,它的行为是相同的。没有相关的编译器警告。
这发生在 Ubuntu 16.04 上,更新了它和所有相关的构建项目。它位于具有大量内存 (8G) 且没有其他任何东西在运行的大型 VM 中。它是 100% 可重现的。该错误发生大约需要 2 秒,这大约是窗口出现通常需要多长时间。
我只是不知道如何修复未被调用的程序中的错误。 :(
更严重的是,我预计这会导致加载的例程或模块中的某种命名冲突,或者它们被搜索的顺序,或者只是一起使用它们时出现一些不兼容,但是实验让我无处可去,我不知道在哪里开始寻找。
有什么建议吗?
添加了 10/27/16 ldd 输出。我在运行版本(代码注释)上做了一个 ldd 并且没有运行,它们是相同的模块,相同(当然不同的地址)。我不知道 MuPDF 使用了 GTK。我查看了它的源代码树,并在一些示例中看到了它(现在我看到了它们,我需要更仔细地查看它们),但我在主查看器中看不到它,尽管它可能以我的形式出现不会认?
但是,我怀疑这是正确的方法,包括 MuPDF 代码会以某种方式拖入与 GTK3 设置不兼容的某些模块。我只是不知道如何找到它(尤其是看到 ldd 输出是一样的)。
ldd TestGTK
linux-vdso.so.1 => (0x00007ffc5bfef000)
libgtk-3.so.0 => /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 (0x00007f2310ad5000)
libgio-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f231074d000)
libgobject-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f23104f9000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f23101f0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f230fe27000)
libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f230f9e2000)
libgdk-3.so.0 => /usr/lib/x86_64-linux-gnu/libgdk-3.so.0 (0x00007f230f707000)
libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f230f503000)
libpangocairo-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f230f2f5000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f230efbb000)
libXi.so.6 => /usr/lib/x86_64-linux-gnu/libXi.so.6 (0x00007f230edab000)
libXfixes.so.3 => /usr/lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f230eba4000)
libcairo-gobject.so.2 => /usr/lib/x86_64-linux-gnu/libcairo-gobject.so.2 (0x00007f230e99b000)
libcairo.so.2 => /usr/lib/x86_64-linux-gnu/libcairo.so.2 (0x00007f230e687000)
libgdk_pixbuf-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007f230e464000)
libatk-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libatk-1.0.so.0 (0x00007f230e23f000)
libatk-bridge-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0 (0x00007f230e010000)
libepoxy.so.0 => /usr/lib/x86_64-linux-gnu/libepoxy.so.0 (0x00007f230dd1a000)
libpangoft2-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x00007f230db04000)
libpango-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x00007f230d8b8000)
libfontconfig.so.1 => /usr/lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f230d674000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f230d363000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f230d146000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f230cf2b000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f230cd09000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f230caed000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f230c8e5000)
/lib64/ld-linux-x86-64.so.2 (0x0000556c9118f000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f230c6e1000)
libXinerama.so.1 => /usr/lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007f230c4dd000)
libXrandr.so.2 => /usr/lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007f230c2d2000)
libXcursor.so.1 => /usr/lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007f230c0c8000)
libXcomposite.so.1 => /usr/lib/x86_64-linux-gnu/libXcomposite.so.1 (0x00007f230bec4000)
libXdamage.so.1 => /usr/lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007f230bcc1000)
libxkbcommon.so.0 => /usr/lib/x86_64-linux-gnu/libxkbcommon.so.0 (0x00007f230ba82000)
libwayland-cursor.so.0 => /usr/lib/x86_64-linux-gnu/libwayland-cursor.so.0 (0x00007f230b879000)
libwayland-egl.so.1 => /usr/lib/x86_64-linux-gnu/libwayland-egl.so.1 (0x00007f230b677000)
libwayland-client.so.0 => /usr/lib/x86_64-linux-gnu/libwayland-client.so.0 (0x00007f230b469000)
libmirclient.so.9 => /usr/lib/x86_64-linux-gnu/libmirclient.so.9 (0x00007f230b1e7000)
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f230afd5000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f230adcd000)
libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f230ab22000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f230a900000)
libpixman-1.so.0 => /usr/lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f230a657000)
libpng12.so.0 => /lib/x86_64-linux-gnu/libpng12.so.0 (0x00007f230a432000)
libxcb-shm.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007f230a22e000)
libxcb-render.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-render.so.0 (0x00007f230a023000)
libXrender.so.1 => /usr/lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f2309e19000)
libatspi.so.0 => /usr/lib/x86_64-linux-gnu/libatspi.so.0 (0x00007f2309be9000)
libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007f230999d000)
libharfbuzz.so.0 => /usr/lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007f230973f000)
libthai.so.0 => /usr/lib/x86_64-linux-gnu/libthai.so.0 (0x00007f2309535000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f230930c000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f230909b000)
libmircommon.so.5 => /usr/lib/x86_64-linux-gnu/libmircommon.so.5 (0x00007f2308e6a000)
libmirprotobuf.so.3 => /usr/lib/x86_64-linux-gnu/libmirprotobuf.so.3 (0x00007f2308c08000)
libboost_system.so.1.58.0 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0 (0x00007f2308a04000)
libprotobuf-lite.so.9 => /usr/lib/x86_64-linux-gnu/libprotobuf-lite.so.9 (0x00007f23087d3000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f2308450000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f230823a000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f2308035000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f2307e2f000)
libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f2307da9000)
libgraphite2.so.3 => /usr/lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007f2307b84000)
libdatrie.so.1 => /usr/lib/x86_64-linux-gnu/libdatrie.so.1 (0x00007f230797c000)
libboost_filesystem.so.1.58.0 => /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.58.0 (0x00007f2307763000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f2307541000)
libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f230725f000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f230704b000)
顺便说一句,这是带有扩展宏的代码,如果删除则允许它运行,如果保留则导致失败(即使从未遇到过代码)。有趣的是,__sigsetjmp 位于 MuPDF 的包含库和 GTK3 示例的不同标头中,但我看不到它正在改变链接的内容,但我怀疑这是相关的。
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot create mupdf context\n");
return EXIT_FAILURE;
}
{ if (fz_push_try(ctx))
{ if (__sigsetjmp ( (ctx)->error->top->buffer,0) == 0)
do
fz_register_document_handlers(ctx);
while (0);
}
}
if ((ctx->error->top--)->code > 1)
{
fprintf(stderr , "cannot register document handlers: %s\n", fz_caught_message(ctx));
fz_drop_context(ctx);
return 1;
}
2016 年 10 月 27 日更新 #2:我可能在自欺欺人,但我认为我越来越近了。失败来自 hb_calloc,它是 harfbuzz 的一部分,实际上包含在 MuPDF 发行版中。看起来 GTK 最终调用了一个名为 pango_shape_full 的东西,它后来调用了 hb_ft_face_create 并通过更多的调用 hb_calloc 断言失败。但是它正在从 MuPDF 包含的源代码内部获取这些例程,这在不涉及 MuPDF 时显然不会发生(为什么,或者即使它与我不知道的特定代码行有关)。
我知道了如何创建链接地图,但不知道如何解释它。例如,hb_calloc 似乎在 crtl 中,它也已加载,但随后它再次出现(至少在清单中更进一步),来自源代码构建的 libmupdf.a 库。我的猜测是这种交叉以某种方式存在问题,尽管我还没有看到为什么,或者如何保持对它的控制或分离。我在链接中重新排列了库的顺序,找不到任何有区别的组合。
在 MuPDF 上也有关于此的负面信息(例如 here),但我对正在发生的事情还不够深入,无法判断它是否相关。但是我确实感觉 MuPDF 中与 harfbuz 相关的代码与通常在 GTK3 上运行的代码相冲突,我以某种方式替换了与 GTK 一起使用的罐装 harfbuz 函数,而有些则没有。我将尝试在 MuPDF 中删除该 c 源代码并重建,但我的猜测是我会用破坏 MuPDF 来交换破坏 GTK,因为我离真正使用它还很远,所以可能需要更长的时间才能找到。
还是我走错了路?
【问题讨论】:
-
也许 MuPDF 链接到其他版本的 GTK 而不是您的应用程序(例如 GTK2 而不是 GTK3)。尝试运行
ldd build/TestGTK。 -
我想我放弃了。我尝试使用 MuPDF 的发行版,但它与 libopenjpeg 链接,显然存在需要重建 MuPDF 的已知问题(未定义的链接时间引用),让我回到了完整的循环。我做了一个 QT5 项目,它产生了相同的结果(但认为如果它构建了 make 文件可能会更聪明)。我尝试了 MuPDF 内容的 .so 和动态加载来隔离冲突的功能,但这需要将 MuPDF 构建为 PIC,我怀疑我能否成功将该线程拉到最后。仍然希望有一个神奇的解决方案?