이 페이지에서

예외 안전성

사전 경고: 예외 안전 기능은 아직 완성되지 않았습니다! 일반적인 경우에는 정상적으로 작동하겠지만, 클래스에서 메모리 누수가 발생하거나 심지어 프로그램이 중단될 수도 있습니다.

Qt 자체는 예외를 발생시키지 않습니다. 대신 오류 코드가 사용됩니다. 또한, 일부 클래스에는 사용자가 볼 수 있는 오류 메시지가 있습니다(예: ` QIODevice::errorString()` 또는 ` QSqlQuery::lastError()`). 이는 역사적 및 실용적인 이유가 있습니다. 예외 처리를 활성화하면 라이브러리 크기가 20% 이상 증가할 수 있습니다.

다음 섹션에서는 컴파일 시점에 예외 처리가 활성화된 경우 Qt의 동작에 대해 설명합니다.

예외 안전 모듈

컨테이너

Qt의 컨테이너 클래스는 일반적으로 예외 중립적입니다. 이 클래스들은 포함된 유형 T 내에서 발생하는 모든 예외를 사용자에게 전달하는 동시에 내부 상태를 유효한 상태로 유지합니다.

예시:

QList<QString> list;
...
try {
    list.append("hello");
} catch (...) {
}
// list is safe to use - the exception did not affect it.

이 규칙의 예외는 할당 또는 복사 생성자 호출 중에 예외를 발생시킬 수 있는 타입을 위한 컨테이너입니다. 이러한 타입의 경우, 컨테이너를 수정하거나 값을 반환하는 함수를 사용하는 것은 안전하지 않습니다:

MyType s = list.takeAt(2);

s 의 할당 과정에서 예외가 발생하면, 인덱스 2에 있던 값은 이미 컨테이너에서 제거되었지만, 아직 s 에 할당되지는 않은 상태입니다. 이 값은 복구할 수 없이 손실됩니다.

올바른 작성 방법은 다음과 같습니다:

MyType s = list.at(2);
list.removeAt(2);

할당 과정에서 예외가 발생하더라도 컨테이너에는 해당 값이 그대로 남아 있으며, 데이터 손실은 발생하지 않습니다.

암시적으로 공유되는 Qt 클래스는 할당 연산자나 복사 생성자에서 예외를 발생시키지 않으므로, 위의 제한 사항은 적용되지 않는다는 점에 유의하십시오.

메모리 부족 처리

대부분의 데스크톱 운영 체제는 메모리를 과다 할당합니다. 즉, 할당 시점에 사용 가능한 메모리가 충분하지 않더라도 ` malloc() ` 또는 ` operator new `은 유효한 포인터를 반환합니다. 이러한 시스템에서는 ` std::bad_alloc ` 유형의 예외가 발생하지 않습니다.

그 외의 모든 운영 체제에서는 할당이 실패할 경우 Qt가 std::bad_alloc 유형의 예외를 발생시킵니다. 시스템의 메모리가 부족하거나 요청된 크기를 할당할 수 있는 충분한 연속 메모리가 없는 경우 할당이 실패할 수 있습니다.

이 규칙에 대한 예외 사항은 문서에 명시되어 있습니다. 예를 들어, QImage 생성자는 메모리가 충분하지 않은 경우 예외를 발생시키는 대신 null 이미지를 생성합니다.

예외로부터의 복구

현재 Qt 내에서 발생한 예외(예: 메모리 부족으로 인한 경우)로부터 복구하는 데 지원되는 유일한 사용 사례는 이벤트 루프를 종료하고, 애플리케이션을 종료하기 전에 일부 정리 작업을 수행하는 것입니다.

일반적인 사용 사례:

QApplication app(argc, argv);
...
int ret;
try {
    ret = app.exec();
} catch (const std::bad_alloc &) {
    // clean up here, e.g. save the session
    // and close all config files.

    return EXIT_FAILURE; // exit the application
}
...
return ret;

예외가 발생된 후에는 윈도우 서버와의 연결이 이미 끊겨 있을 수 있습니다. 예외를 처리한 후 GUI 관련 함수를 호출하는 것은 안전하지 않습니다.

클라이언트 코드 내의 예외

시그널과 슬롯

Qt의 시그널-슬롯 연결 메커니즘을 통해 호출된 슬롯에서 예외를 발생시키는 것은, 해당 슬롯 내에서 처리되지 않는 한 정의되지 않은 동작으로 간주됩니다:

State state;
StateListener stateListener;

// OK; the exception is handled before it leaves the slot.
QObject::connect(&state, SIGNAL(stateChanged()), &stateListener, SLOT(throwHandledException()));
// Undefined behaviour; upon invocation of the slot, the exception will be propagated to the
// point of emission, unwinding the stack of the Qt code (which is not guaranteed to be exception safe).
QObject::connect(&state, SIGNAL(stateChanged()), &stateListener, SLOT(throwUnhandledException()));

일반 함수 호출처럼 슬롯이 직접 호출된 경우에는 예외를 사용할 수 있습니다. 이는 슬롯을 직접 호출할 때 연결 메커니즘이 우회되기 때문입니다:

State state;
StateListener stateListener;

// ...

try {
    // OK; 슬롯을 직접 호출하고 있습니다.
    stateListener.throwException();
} catch (...) {
    qDebug() << "Handling exception not caught in slot.";
}

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.