Error Reporting
GLib забезпечує стандартний метод повідомлення про помилки з викликаної функції у коді, що викликається. (Це також вирішує проблему виняткової ситуації іншими мовами). Важливо зрозуміти що це метод - data type (GError об'єкт) та набору правил. Якщо ви використовуєте GError неправильно, ваш код не буде правильно взаємодіяти з іншим кодом, що використовує GError , а користувачі вашого API ймовірно заплутаються.
Перш за все: GError повинен використовуватися тільки для повідомлення про помилки, що відновлюються в процесі виконання. Зазвичай ви повинні використовувати g_warning() , g_return_if_fail() , g_assert() , g_error() або схожий засіб. (пам'ятайте, що функція g_error() повинна використовуватися тільки для програмних помилок, вона не повинна використовуватися для друку будь-якої помилки, про яку повідомлено через GError .)
Прикладом помилок, що відновлюються під час виконання програми є "file not found" (файл не знайдений) або "failed to parse input" (не вдається проаналізувати введення). Прикладом програмних помилок є "NULL passed to strcmp() " або "attempted to free the same pointer twice". Ці два види помилок суттєво відрізняються: помилки під час виконання повинні оброблятися або про них має бути повідомлено користувачеві, програмні помилки повинні ліквідуватись виправленням у програмі. Тому більшість функцій GLib і GTK+ не використовують GError .
Функції які можуть завершитися невдало приймають як останній параметр місце розташування повертається GError. Наприклад:
Якщо ви помістили не- NULL значення у параметр error , він повинен вказувати місце куди може бути поміщена помилка. Наприклад:
Пам'ятайте, що err != NULL у цьому прикладі надійно перевіряє чи не закінчилася невдачею g_file_get_contents() . Додатковоg_file_get_contents() повертає логічне, яке вказує, чи була вона завершена вдало.
Оскільки g_file_get_contents() повертає FALSE при невдачі, якщо ви цікавитеся лише статусом завершення і не потребуєте відображення повідомлення про помилку, ви можете помістити NULL у параметр error :
Об'єкт GError містить три поля: domain вказує функцію повідомлення про помилки, code вказує специфічну помилку, що відбулася, а message читабельне для користувача повідомлення, яке більш детально описує помилку наскільки це можливо. Деякі функції призначені для зв'язку з помилкою отриманої з функції, що викликається: g_error_matches() повертає TRUE якщо помилка відповідає даній domain і code, g_propagate_error() копіює помилку в місце зберігання помилки (таким чином викликана функція отримує її), а g_clear_error() очищає місце розташування помилки звільняючи помилку і встановлюючи місце зберігання помилки в NULL . Для відображення помилки користувачеві, просто відобразіть error->message , можливо поряд з додатковим контекстом відомим тільки викликається функції (відкривається файл, або будь-який - хоча у випадку g_file_get_contents() , error->message вже містить ім'я файлу).
При реалізації функцій, здатних повідомляти про помилки, основний інструмент g_set_error() . Зазвичай, якщо відбувається фатальна помилка, вам потрібна g_set_error() , потім негайне завершення. g_set_error() нічого не робить якщо розташування помилки поміщене до неї NULL . Наприклад:
Трохи складніше, якщо ви самостійно викликаєте функцію, яка може повідомити GError. Якщо підлегла функція вказує на невиправні помилки деяким способом, що відрізняється від повідомлення GError , таким як повернення TRUE при вдалому виконанні, ви можете просто зробити таке:
Якщо підлегла функція не вказує про інші помилки окрім повідомлення GError, ви повинні створити тимчасову GError так як поміщається в неї може бути NULL. У цьому випадку використовується g_propagate_error().
Error pileups завжди є помилкою. Наприклад, цей код неправильний:
tmp_error повинна бути перевірена негайно після sub_function_that_can_fail() , або очищена або поширена на верх. Правило: після кожної помилки, ви повинні або обробити помилку, або повернути її в функцію . Пам'ятайте, що NULL для параметра розташування помилки еквівалентно обробці помилки нічого не роблячи з нею. Таким чином наступний код є хорошим прикладом, передбачається, що помилки в sub_function_that_can_fail() є не фатальними для my_function_that_can_fail() :
Пам'ятайте, що NULL, що міститься, у параметр розміщення помилки означає ігнорування помилок; це еквівалентно try < sub_function_that_can_fail(); >catch (. ) <> у C++. Це означає залишити помилки не обробленими; це означає обробити помилки нічого не роблячи.
Області та коди помилки зазвичай іменуються так:
Область помилки називають згідно з шаблоном _ _ERROR , наприклад G_EXEC_ERROR або G_THREAD_ERROR .
Коди помилки перебувають у перерахуванні званому згідно з шаблоном Error ; наприклад, GThreadError або GSpawnError .
Елементи перерахування кодів помилки називаються згідно з шаблоном _ _ERROR_ , наприклад G_SPAWN_ERROR_FORK або G_THREAD_ERROR_AGAIN .
Якщо є "generic" або "unknown" коди помилки для невиправних помилок, немає сенсу розрізняти їх іншими специфічними кодами, вони повинні бути названі за шаблоном _ _ERROR_FAILED , наприклад G_SPAWN_ERROR_FAILED or G_THREAD_ERROR_FAILED .
Зведені правила використанняGError:
Не повідомляйте про програмні помилки через GError.
Останнім параметром функції повертає помилку має бути місце розташування GError (тобто "GError** error"). Якщо GError використовується зі змінною кількістю аргументів, то GError** має бути останнім аргументом перед ".".
Виклик може поміщати NULL для GError ** якщо його не цікавлять подробиці помилки.
Якщо NULL поміщений для GError ** аргументу, тоді помилка не повинна повертатися до зухвалої функції, але ваша функція все ж таки повинна перериватись і повертатися якщо відбулася помилка. Таким чином, на керування потоком не повинно впливати отримання або неотримання викликаючою функцією GError .
Якщо про GError повідомлено, то ваша функція за визначенням має фатальну помилку і не закінчила те, що повинна була зробити. Якщо відбулася не фатальна помилка, то ви обробляєте її і не повинні повідомляти про неї. Якщо вона була фатальною, ви повинні повідомити про неї і припинити виконання негайно.
"Накопичення" помилок - завжди помилка. Таким чином, якщо ви призначили нову GError для GError * яка не- NULL , переписуючи таким чином попередню помилку, вона вказує вам, що потрібно перервати операцію замість продовження. Ви можете продовжувати, якщо очистите попередню помилку за допомогою g_clear_error() . g_set_error() буде попереджати, якщо ви накопичуєте помилки.
У відповідність до угоди, якщо ви повертаєте логічне значення, то TRUE означає успішне виконання, а FALSE означає невдачу. Якщо повернуто значення FALSE , помилка повинна бути встановлена на значення NULL .
Повернене значення NULL часто також означає, що сталася помилка. Ви повинні роз'яснити у вашій документації чи означає NULL допустиме значення, що повертається ву разі безпомилкового виконання; якщо NULL допустиме значення, то користувачі повинні перевірити чи була повернена помилка, щоб побачити, чи функція успішно.
Коли реалізується функція яка може повідомляти про помилки, ви можете додати перевірку на початку вашої функції чи місце розташування помилки значенням NULL або чи використовується значення NULL як покажчик помилки (наприклад g_return_if_fail (error == NULL *error == NULL); ).
Структура GError містить інформацію про помилку.
| GQuark domain; | область помилки, наприклад, G_FILE_ERROR . |
| gint code; | код помилки, наприклад G_FILE_ERROR_NOENT . |
| gchar *message; | зручне для читання користувачем інформаційне повідомлення про помилку. |
g_error_new()
Створює нову GError з отриманими domain та code, а повідомлення форматується за допомогою format.
| domain : | область помилки |
| code : | код помилки |
| format : | printf() -стиль форматування для повідомлення про помилку |
| . : | параметри для форматування повідомлення |
| Повертає: | нова GError |
g_error_new_literal()
Створює нову GError; на відміну від g_error_new() , message є рядком над printf() -стилі форматування. Використовуйте цю функцію, якщо message містить текст не контрольований вами, який міг би включати escape-послідовність printf().
| domain : | область помилки |
| code : | код помилки |
| message: | повідомлення про помилку |
| Повертає: | нова GError |
g_error_free()
Звільняє GError і пов'язані зній ресурси.