Как правильно управлять ссылками, возвращаемыми g_dbus_interface_get_object () - PullRequest
0 голосов
/ 22 февраля 2020

У меня есть приложение, в котором я использую UDisks для обработки некоторых дисков и разделов. В моем приложении есть ситуация, когда у меня есть указатель на UDisksDrive, который мне нужно преобразовать в указатель UDisksObject, через который я смогу получить доступ к другим интерфейсам позже. Мне совершенно неясно, к каким объектам я должен обращаться и когда. В настоящее время я выполняю одну функцию:

    UDisksDrive* drive = udisks_client_get_drive_for_block(client, block);
    if(drive == NULL) {
        g_object_unref(block);
        return NULL;
    }

    UDisksObject* driveObject = (UDisksObject*) g_dbus_interface_get_object(G_DBUS_INTERFACE(drive));
    g_object_unref(drive);
    return driveObject;

Но я не знаю, правильно ли это. Это работает, но я знаю, что это не обязательно что-то значит. Документация по gdbus для g_dbus_interface_get_object() гласит, что я не должен ссылаться на возвращенную переменную driveObject, когда получающая функция завершена, но я не уверен. Я чувствую, что я не должен ссылаться на block до того, как функции тоже вернутся, но я не знаю, почему это не так Это проект, над которым у меня есть только время, чтобы работать здесь и там, и я чувствую, что, возможно, я попробовал его, и это вызвало cra sh или исключение.

Большая часть моего другого кода, включающего UDisks, это довольно просто. Я _get_ что-то использую, и не ссылаюсь на это. Это то, что связано со сменой интерфейса, о которой я немного размыта.

1 Ответ

0 голосов
/ 24 февраля 2020

Время подумать, изучить и поболтать о IR C привело к следующему:

Да, мне определенно нужно освободить (unreference) block, прежде чем функция вернется. Кроме того, g_dbus_interface_get_object() является неправильной функцией для этой ситуации. Поскольку меня не волнует drive и я просто хочу вернуть driveObject, мне нужно вместо этого использовать g_dbus_interface_dup_object(), что позволяет возвращаемому указателю иметь собственную ссылку. Это делает так, что вызывающий абонент может безопасно высвободить driveObject, когда это будет сделано. Таким образом, обновленный фрагмент кода выглядит следующим образом:

    UDisksDrive* drive = udisks_client_get_drive_for_block(client, block);
    if(drive == NULL) {
        g_object_unref(blockObject);
        g_object_unref(block);
        return NULL;
    }

    UDisksObject* driveObject = (UDisksObject*) g_dbus_interface_dup_object(G_DBUS_INTERFACE(drive));
    g_object_unref(block);
    g_object_unref(drive);
    g_object_unref(blockObject);

    return driveObject;
...