了解 gjs 内存管理警告

问题描述 投票:0回答:1

我是

gjs
gtk
的新手,所以这可能是非常基本的,但我没有发现任何其他与此相关的问题。

在尝试了解 gtk 和 gdk 的 gjs 绑定时,我想编写一个小脚本来记录将打开窗口的监视器的尺寸,因此我想出了以下脚本:

import Gtk from 'gi://Gtk?version=4.0'
import Gdk from 'gi://Gdk?version=4.0'

// Gtk needs to be initialized to get a non-null default display, I think
Gtk.init()

const {Display, Surface} = Gdk
const display = Display.get_default()
const surface = Surface.new_toplevel(display)

const {geometry: {width, height}} = display.get_monitor_at_surface(surface)
console.log(`Width:  ${width}`)
console.log(`Height: ${height}`)
surface.destroy()

虽然此脚本成功退出(状态代码 0),但它会记录类似以下行的内容:

(gjs:12345): Gjs-CRITICAL **: 00:00:00.000: Object 0x112233445566 of type GdkWaylandToplevel has been finalized while it was still owned by gjs, this is due to invalid memory management.

但是,以下实验让我对如何适当修改此脚本感到困惑:

  • 删除
    surface.destroy()
    行会记录一条警告:
    losing last reference to undestroyed surface
    ,这似乎很公平,因为该表面没有被破坏。
  • 添加一行
    console.log('appended')
    记录该消息,因此销毁表面不会引发任何错误(我在确保原始脚本的状态代码为 0 之前对此进行了测试);但是,我不知道其他事情是否可能会触发错误(例如运行 GLib 主循环)。

在此脚本中管理内存的适当方法是什么?

编辑:

在集成获取的尺寸以运行具有适当大小的嵌套 Wayland 会话时,我意识到当脚本自行完成时会记录关键消息,而不是在通过 Ctrl+C 中止时记录关键消息。不记录任何不相关消息的最小工作示例是:

import Gtk from 'gi://Gtk?version=4.0'
import Gdk from 'gi://Gdk?version=4.0'
import Gio from 'gi://Gio'

Gtk.init()

const {Display, Surface} = Gdk
const {Subprocess, SubprocessFlags: {SEARCH_PATH_FROM_ENVP}} = Gio

Gio._promisify(Subprocess.prototype, 'wait_async', 'wait_finish')

const display = Display.get_default()
const surface = Surface.new_toplevel(display)
const {geometry: {width, height}} = display.get_monitor_at_surface(surface)
surface.destroy()

await Subprocess.new(
  ['sleep', '5'],
  SEARCH_PATH_FROM_ENVP
).wait_async(null)

正如之前所解释的,如果我们在运行此脚本后等待 5 秒,脚本会自行完成并记录关键消息;但是,如果我们在此之前按 Ctrl+C,它将中止并且该消息永远不会被记录。

gtk gjs
1个回答
0
投票

在销毁表面之前执行

surface.ref()
消除了该消息。

import Gtk from 'gi://Gtk?version=4.0'
import Gdk from 'gi://Gdk'

// Gtk needs to be initialized to get a non-null default display, I think
Gtk.init()

const {Display, Surface} = Gdk
const display = Display.get_default()
const surface = Surface.new_toplevel(display)

const {geometry: {width, height}} = display.get_monitor_at_surface(surface)
console.log(`Width:  ${width}`)
console.log(`Height: ${height}`)
surface.ref()
surface.destroy()

我仍然不明白为什么,但根据@andy.holmes的建议,我在

gjs
项目上提出了一个问题。我将根据我收到的相关反馈更新此答案。

© www.soinside.com 2019 - 2024. All rights reserved.