为什么我的Gdk / cairo类会导致段错误?

时间:2017-10-20 10:03:06

标签: segmentation-fault cairo gdk gjs

我编写了一个小类,用base64编码的JPEG bytearray创建一个圆形图像,但它似乎经常导致段错误。这是我在GJS中创建cairo表面的最简单方法,虽然我不反对Clutter,如果它解决了我的问题。

var CircularImage = new Lang.Class({
    Name: "CircularImage",
    Extends: Gtk.DrawingArea,

    _init: function (bytearray, win, size) {
        this.parent({
            height_request: size,
            width_request: size
        });

        this.size = size;

        let image_stream = Gio.MemoryInputStream.new_from_data(
            GLib.base64_decode(bytearray),
            GLib.free
        );

        let pixbuf = GdkPixbuf.Pixbuf.new_from_stream(
            image_stream,
            null
        )

        pixbuf.scale_simple(this.size, this.size, GdkPixbuf.InterpType.HYPER);

        this._surface = Gdk.cairo_surface_create_from_pixbuf(
            pixbuf,
            0,
            win.get_window()
        );

        this.connect("draw", (widget, cr) => {
            this._draw(widget, cr);
            return false;
        });
    },

    _draw: function (widget, cr) {
        cr.setSourceSurface(this._surface, 0, 0);
        cr.arc(this.size/2, this.size/2, this.size/2, 0, 2*Math.PI);
        cr.clip();
        cr.paint();
    }
});

似乎没有针对CairoImageSurface的破坏功能或信号,我尝试不用pixbuf查看是否有帮助,但这会导致错误:

  

GLib-GObject-WARNING **:g_object_remove_toggle_ref:找不到切换参考号0x7f45456b19e0((nil))

我在一个简单的Gtk窗口中使用它并且它可以工作,但它似乎导致段错误大约一半的时间。我对内存管理知之甚少,因为我通常使用垃圾收集语言,所以我只假设这与内存有关,我没有释放。

有什么明显的东西我做错了,使用Clutter更简单的方法或简单的方法我可以追踪任意的段错误吗?

1 个答案:

答案 0 :(得分:2)

即使底层库需要,您也不必处理GJS中的内存管理。如果你这样做,那就是一个bug。无论如何试图这样做肯定会导致崩溃。 (因此,即使您在GJS文档中看到任何调用GObject.unref()let image_stream = Gio.MemoryInputStream.new_from_bytes( GLib.base64_decode(bytearray).toGBytes()); 的说明 - 它们也会从C文档自动生成,不应该在那里。)

不幸的是,这些需要您关心内存管理的错误仍然存​​在,其中两个与您的代码段相关。

您现在遇到的错误就是这个:https://bugzilla.gnome.org/show_bug.cgi?id=747431 相反,做这样的事情:

draw

另一个可能在以后变得相关的GJS错误是,当您连接到cr.$dispose()信号时,您当前必须在开罗上下文中调用material-content { max-height: 100%; overflow-y: scroll; } ,否则内存将被泄露。