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

Why is my Gdk/cairo class causing a segfault?

我已经写了一个小 class 来从 base64 编码的 JPEG 字节数组创建一个圆形图像,但它似乎经常导致段错误。这是我能找到的在 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: couldn't find toggle ref 0x7f45456b19e0((nil))

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

是否有明显的错误,使用 Clutter 的更简单方法或我可以追踪任意段错误的简单方法?

即使底层库需要,您也不必在 GJS 中处理内存管理。如果你这样做,那就是一个错误。无论如何尝试这样做肯定会导致崩溃。 (因此,如果您看到任何调用 GLib.free()GObject.unref() 的说明,即使在 GJS 文档中 — 它们是从 C 文档自动生成的,不应该存在。)

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

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

let image_stream = Gio.MemoryInputStream.new_from_bytes(
    GLib.base64_decode(bytearray).toGBytes());

另一个 GJS 错误可能会在以后变得相关,当您连接到 draw 信号时,您当前必须在 Cairo 上下文中调用 cr.$dispose() 否则内存将被泄漏。