Как закончить код на С++

Я бы хотел, чтобы мой код на С++ прекратил работу, если выполнено определенное условие, но я не уверен, как это сделать. Поэтому в любой момент, если инструкция if истинна, завершите код следующим образом:

if (x==1)
{
    kill code;
}

Ответ 1

Существует несколько способов, но сначала вам нужно понять, почему важно очистить объект, и поэтому причина std::exit является маргинальной среди С++ программисты.

RAII и Stack Unwinding

С++ использует идиому под названием RAII, которая в простых терминах означает, что объекты должны выполнять инициализацию в конструкторе и очищать в деструкторе, Например, std::ofstream класс [может] открыть файл во время конструктора, тогда пользователь выполняет на нем выходные операции и, наконец, в конце своего жизненного цикла, обычно определяемого его областью, деструктор называется тем, что существенно закрывает файл и сбрасывает любое записанное содержимое на диск.

Что произойдет, если вы не дойдете до деструктора, чтобы сбросить и закрыть файл? Кто знает! Но, возможно, он не будет записывать все данные, которые он должен был записать в файл.

Например, рассмотрим этот код

#include <fstream>
#include <exception>
#include <memory>

void inner_mad()
{
    throw std::exception();
}

void mad()
{
    std::unique_ptr<int> ptr(new int);
    inner_mad();
}

int main()
{
    std::ofstream os("file.txt");
    os << "Content!!!";

    int possibility = /* either 1, 2, 3 or 4 */;

    if(possibility == 1)
        return 0;
    else if(possibility == 2)
        throw std::exception();
    else if(possibility == 3)
        mad();
    else if(possibility == 4)
        exit(0);
}

Что происходит в каждой возможности:

  • Возможность 1: Возврат существенно оставляет текущую область действия, поэтому он знает о конце жизненного цикла os, тем самым называя его деструктор и делая правильную очистку, закрывая и промывая файл до диск.
  • Возможность 2: Выбрасывание исключения также заботится о жизненном цикле объектов в текущей области действия, тем самым делая правильную очистку...
  • Возможность 3: Здесь стекается разматывание в действии! Несмотря на то, что исключение выбрано в inner_mad, разматыватель будет проходить через стек mad и main для правильной очистки, все объекты будут разрушены должным образом, включая ptr и os.
  • Возможность 4: Ну, здесь? exit является функцией C и не знает и не совместим с идиомами С++. Он не выполняет выполнять очистку ваших объектов, включая os в той же области. Таким образом, ваш файл не будет закрыт должным образом, и по этой причине контент никогда не будет записан в него!
  • Другие возможности:. Он просто оставит основную область, выполнив неявный return 0 и, таким образом, получив тот же эффект, что и возможность 1, т.е. правильная очистка.

Но не будьте так уверенны в том, что я только что сказал вам (в основном возможности 2 и 3); продолжить чтение, и мы узнаем, как выполнить правильную очистку на основе исключений.

Возможные пути завершения

Возврат из main!

Вы должны делать это, когда это возможно; всегда предпочитают возвращаться из вашей программы, возвращая правильный статус выхода из основного.

Вызывающая ваша программа и, возможно, операционная система могут захотеть узнать, успешно ли выполнена ваша программа или нет. По этой же причине вы должны вернуть либо ноль, либо EXIT_SUCCESS, чтобы сообщить, что программа успешно завершена, и EXIT_FAILURE, чтобы сигнализировать о завершении неудачной программы, любая другая форма возвращаемого значения определяется реализацией (§18.5/8).

Однако вы можете быть очень глубоки в стеке вызовов и вернуть все это может быть больно...

[Не создавать] исключение

Бросок исключений будет выполнять правильную очистку объекта с помощью разворачивания стека, вызывая деструктор каждого объекта в любой предыдущей области.

Но вот catch! Это реализация определяет, выполняется ли разматывание стека, когда исключение броска не обрабатывается (по предложению catch (...)) или даже если у вас есть noexcept в середине стека вызовов. Об этом говорится в §15.5.1 [except.terminate]:

  • В некоторых ситуациях обработка исключений должна быть отменена для менее тонких методов обработки ошибок. [Примечание: Эти ситуации:

    [...]

         

    - , когда механизм обработки исключений не может найти обработчик для генерируемого исключения (15.3) или когда поиск обработчика (15.3) встречает самый внешний блок функции с noexcept -спецификацией, который не допускает исключения (15.4) или [...]

         

    [...]

  • В таких случаях вызывается std:: terminate() (18.8.3). В ситуации, когда соответствующий обработчик не найден, он определяется реализацией независимо от того, разрывается ли стек до того, как std:: terminate() вызывается [...]

Итак, мы должны его поймать!

Бросьте исключение и поймайте его на главном!

Так как неотображаемые исключения могут не выполнять разворачивание стека (и, следовательно, не будут выполнять надлежащую очистку), мы должны поймать исключение в основном, а затем вернуть статус выхода (EXIT_SUCCESS или EXIT_FAILURE).

Таким образом, возможно, хорошая настройка:

int main()
{
    /* ... */
    try
    {
        // Insert code that will return by throwing a exception.
    }
    catch(const std::exception&)  // Consider using a custom exception type for intentional
    {                             // throws. A good idea might be a `return_exception`.
        return EXIT_FAILURE;
    }
    /* ... */
}

[Не выполнять] std:: exit

Это не выполняет какой-либо раскрутки стека, и ни один живой объект в стеке не вызовет его соответствующий деструктор для выполнения очистки.

Это применяется в §3.6.1/4 [basic.start.init]:

Завершение работы программы без выхода из текущего блока (например, путем вызова функции std:: exit (int) (18.5)) не уничтожает объекты с автоматическим временем хранения (12.4). Если std:: exit вызывается для завершения программы во время уничтожения объекта со статикой или продолжительностью хранения потоков, программа имеет поведение undefined.

Подумайте об этом сейчас, зачем вам это делать? Сколько объектов вы пострадали от боли?

Другие [как плохие] альтернативы

Существуют и другие способы прекращения программы (кроме сбоев), но они не рекомендуются. Только для разъяснения они будут представлены здесь. Обратите внимание, что нормальное завершение программы не означает сброс стека, но состояние в операционной системе.

  • std::_Exit вызывает нормальное завершение программы и что оно.
  • std::quick_exit вызывает обычное завершение программы и вызывает std::at_quick_exit, никакая другая очистка не выполняется.
  • std::exit вызывает нормальное завершение программы, а затем вызывает std::atexit. Другие виды очистки выполняются, например, вызов деструкторов статических объектов.
  • std::abort вызывает ненормальное завершение программы, никакая очистка не выполняется. Это следует назвать, если программа завершилась действительно, действительно неожиданным образом. Он ничего не сделает, кроме как сигнализирует ОС об аномальном завершении. В этом случае некоторые системы выполняют сброс ядра.
  • std::terminate вызывает std::terminate_handler, который звонит std::abort по умолчанию.

Ответ 2

Как упоминал Мартин Йорк, выход не выполняет необходимую очистку, например, возврат.

Всегда лучше использовать возврат в месте выхода. Если вы не находитесь в основном, где бы вы хотели выйти из программы, сначала вернитесь к главному.

Рассмотрим приведенный ниже пример. В следующей программе будет создан файл с указанным контентом. Но если return комментируется и uncommented exit (0), компилятор не гарантирует, что файл будет иметь необходимый текст.

int main()
{
    ofstream os("out.txt");
    os << "Hello, Can you see me!\n";
    return(0);
    //exit(0);
}

Не только это. Наличие нескольких точек выхода в программе сделает отладку более сложной. Используйте exit только тогда, когда это может быть оправдано.

Ответ 3

Вызвать функцию std::exit.  

Ответ 4

Люди говорят "call exit (код возврата)", но это плохая форма. В небольших программах это нормально, но с этим связано несколько проблем:

  • В результате у вас будет несколько точек выхода из программы
  • Он делает код более запутанным (например, с помощью goto)
  • Он не может освободить память, выделенную во время выполнения

Действительно, единственный раз, когда вы должны выйти из проблемы, это строка в main.cpp:

return 0;

Если вы используете exit() для обработки ошибок, вы должны узнать об исключениях (и исключениях вложенности), как более элегантный и безопасный метод.

Ответ 5

return 0; поместите это, где хотите, в int main(), и программа немедленно закроется.

Ответ 6

Верните значение из main или используйте функцию exit. Оба берут int. Неважно, какое значение вы вернете, если у вас нет внешнего процесса, смотрящего на возвращаемое значение.

Ответ 7

Программа завершится, когда поток выполнения достигнет конца основной функции.

Чтобы прервать его до этого момента, вы можете использовать функцию exit (int status), где status - это значение, возвращаемое для запуска программы. 0 обычно указывает состояние без ошибок

Ответ 8

Если у вас есть ошибка где-то глубоко в коде, то либо выбросите исключение, либо установите код ошибки. Всегда лучше создавать исключение вместо установки кодов ошибок.

Ответ 9

Как правило, вы должны использовать метод exit() с соответствующим статусом выхода.

Ноль будет означать успешное выполнение. Не нулевой статус указывает на какую-то проблему. Этот код выхода используется родительскими процессами (например, сценариями оболочки), чтобы определить, успешно ли выполняется процесс.

Ответ 10

Помимо вызова exit (error_code) - который вызывает обработчики atexit, но не RAII-деструкторы и т.д. - все больше я использую исключения.

Все больше и больше моя основная программа выглядит как

int main(int argc, char** argv) 
{
    try {
        exit( secondary_main(argc, argv );
    }
    catch(...) {
        // optionally, print something like "unexpected or unknown exception caught by main"
        exit(1);
    }
}

где secondary_main в котором все вещи, которые изначально были поставлены, т.е. исходный основной объект переименован в secondary_main, и добавляется основной заглушка. Это всего лишь тонкость, так что между лотком и уловом не слишком много кода.

Если вы хотите, поймайте другие типы исключений.
Мне очень нравится захватывать строковые типы ошибок, например std::string или char *, и печатать эти в обработчике уловов в основном.

Использование таких исключений, по крайней мере, позволяет вызвать деструкторы RAII, чтобы они могли выполнять очистку. Что может быть приятным и полезным.

В целом, обработка ошибок C - выход и сигналы - и обработка ошибок С++ - try/catch/throw exceptions - в лучшем случае играют вместе непоследовательно.

Затем, когда вы обнаруживаете ошибку

throw "error message"

или более конкретный тип исключения.

Ответ 11

Чтобы разбить условие, используйте return (0);

Итак, в вашем случае это будет:

    if(x==1)
    {
        return 0;
    }

Ответ 12

Если ваш оператор if находится в Loop Вы можете использовать

 break; 

Если вы хотите избежать некоторого кода и продолжить цикл Используйте:

продолжить

Если ваш оператор if не в Loop Вы можете использовать:

 return 0;

Or 




  exit();

Ответ 13

Функция dude... exit() определена в stdlib.h

Итак, вам нужно добавить препроцессор.

Поместите include stdlib.h в раздел заголовка

Затем используйте exit(); везде, где захотите, но не забудьте указать номер интергера в скобках выхода.

например:

exit(0);

Ответ 14

Если условие, которое я тестирую, это действительно плохие новости, я делаю это:

*(int*) NULL= 0;

Это дает мне хороший coredump, откуда я могу проверить ситуацию.