openlang

Может ли main() задавать статус завершения, не нарушая поток управления?

Статус завершения обязательно задавать через os.exit()? Вызов os.exit() внутри main() не позволяет использовать defer и выдаёт такую диагностику:

Error: Unreachable defer statement due to diverging procedure call at the end of the current scope

В этом GitHub Discussion предлагается следующий подход:

Могут ли процедуры main в Odin возвращать значение? - GitHub Discussion (https://github.com/odin-lang/Odin/discussions/3097) Чтобы, например, имитировать int main() из C, заведите отдельную процедуру вроде run, возвращающую значение. Тогда main просто вызывает её и должным образом реагирует на возвращённую ошибку - возможно, вызывая os.exit() со статусом неудачи или выполняя другое действие, нужное приложению.

Может ли main() задать статус завершения иначе, позволяя return, defer и остальным конструкциям управления работать как обычно.

Переведено с английскогоПоказать оригинал

Разговор продолжается 3

Следуя доводам
  1. Ссылка на ответ

    Вызов os.exit() также влияет на то, будут ли в действительности выполняться блоки @(fini). Документация os.exit() говорит:

    документация os.exit (pkg.odin-lang.org) (https://pkg.odin-lang.org/core/os/#exit) ВАЖНО: Блоки @(fini) не выполняются. Чтобы выполнить очистку @(fini), сначала вызовите runtime._cleanup_runtime.

    Переведено с английскогоПоказать оригинал
  2. Ссылка на ответ

    Следующий вариант позволяет совместить os.exit с return, defer, статусом завершения и блоками @fini:

    package main
    
    import "core:fmt"
    import "core:os"
    import "base:runtime"
    
    status_value: int
    main :: proc() {
        defer fmt.println("message deferred")
        if should_stop {
            status_value = 7
            return
        } else {
            status_value = 2
        }
        fmt.println("arbitrary message")
    }
    
    @fini
    finish :: proc "contextless" () {
        context = runtime.default_context()
        fmt.println("Program is terminating.")
        os.exit(status_value)
    }
    Переведено с английскогоПоказать оригинал
  3. Ссылка на ответ

    Вынесите код, который может завершиться ошибкой, в отдельную функцию вместо работы с самим main.

    handle: ^TaskResource
    
    execute :: proc() -> (problem: TaskError) {
        // ...
    }
    
    main :: proc() {
        problem: TaskError
        defer if problem != nil do os.exit(2)
    
        {
            // In place of .fini
            handle = alloc()
            defer release(handle)
    
            problem = execute()
        }
    }

    Обычно такой же шаблон используют для настройки собственного аллокатора/логгера в разных режимах (например, debug), не трогая саму реализацию. Так среда выполнения Odin тоже остаётся доступной.

    Переведено с английскогоПоказать оригинал

Другие стороны того же вопроса

  1. Как обнаружить отсутствие входного файла

    Здравствуйте, возникла трудность с моим скриптом. Поиск в интернете решения не дал. В папку ежедневно (по крайней мере в теор…

    Ответы 2Последняя активность powershell
  2. Отрицание в F# при проверке существования файла

    Использую этот код, чтобы сообщать об ошибке, если файла нет. Вместо этого появляется такая ошибка. Что я неправильно понял?

    Ответы 2Последняя активность fsharp
  3. Уведомления по почте об исключениях и ошибках приложения

    Хочу отправлять письмо всякий раз, когда в приложении возникает ошибка. исключение, имя файла .go и номер его строки. нам это…

    Ответы 2Последняя активность go