나는 무언가가 throw
n 일 때 스택이 잡힌 지점까지 '해제'되고 각 함수 컨텍스트의 스택에있는 클래스 인스턴스의 소멸자가 실행된다는 것을 이해합니다 (소멸자에서 예외를 던져서는 안되는 이유입니다 -당신은 두 번째 것을 던질 수 있습니다) ...하지만 이것이 발생하는 동안 내가 던진 물건이 기억에 어디에 저장되는지 궁금합니다.
구현에 따라 다릅니 까? 그렇다면 가장 널리 사용되는 컴파일러에서 사용하는 특정 방법이 있습니까?
나는 무언가가 throw
n 일 때 스택이 잡힌 지점까지 '해제'되고 각 함수 컨텍스트의 스택에있는 클래스 인스턴스의 소멸자가 실행된다는 것을 이해합니다 (소멸자에서 예외를 던져서는 안되는 이유입니다 -당신은 두 번째 것을 던질 수 있습니다) ...하지만 이것이 발생하는 동안 내가 던진 물건이 기억에 어디에 저장되는지 궁금합니다.
구현에 따라 다릅니 까? 그렇다면 가장 널리 사용되는 컴파일러에서 사용하는 특정 방법이 있습니까?
raise
) 파기하십시오. 힙 할당의 문제는 예외 할당 시도가 실패하면 어떻게합니까? 중단해야합니다 (공간 부족으로 인해 스택에 "실패"하는 경우 스택 오버플로와 마찬가지로). Java와 달리 구현은 대신 다른 예외를 throw 할 수 없습니다.
답변:
예, 대답은 컴파일러에 따라 다릅니다.
내 컴파일러 ( g++ 4.4.3
)를 사용한 빠른 실험 은 런타임 라이브러리가 먼저 malloc
예외에 대해 메모리를 시도하고 실패하면 데이터 세그먼트에있는 프로세스 전체 "비상 버퍼"내에 공간을 할당하려고 시도한다는 것을 보여줍니다. 그래도 해결되지 않으면 std::terminate()
.
비상 버퍼의 주요 목적은 std::bad_alloc
프로세스의 힙 공간이 부족한 후에 throw 할 수 있는 것 같습니다 (이 경우 malloc
호출이 실패 함).
관련 기능은 __cxa_allocate_exception
다음과 같습니다.
extern "C" void *
__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
{
void *ret;
thrown_size += sizeof (__cxa_refcounted_exception);
ret = malloc (thrown_size);
if (! ret)
{
__gnu_cxx::__scoped_lock sentry(emergency_mutex);
bitmask_type used = emergency_used;
unsigned int which = 0;
if (thrown_size > EMERGENCY_OBJ_SIZE)
goto failed;
while (used & 1)
{
used >>= 1;
if (++which >= EMERGENCY_OBJ_COUNT)
goto failed;
}
emergency_used |= (bitmask_type)1 << which;
ret = &emergency_buffer[which][0];
failed:;
if (!ret)
std::terminate ();
}
// We have an uncaught exception as soon as we allocate memory. This
// yields uncaught_exception() true during the copy-constructor that
// initializes the exception object. See Issue 475.
__cxa_eh_globals *globals = __cxa_get_globals ();
globals->uncaughtExceptions += 1;
memset (ret, 0, sizeof (__cxa_refcounted_exception));
return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
}
이 계획이 얼마나 전형적인 지 모르겠습니다.
malloc
호출이 실패 할 것"입니다. 보통은 아니지만 반드시 그런 것은 아닙니다.
에서 이 페이지 :
예외가 발생하려면 스토리지가 필요합니다. 이 저장소는 처리기에서 사용되므로 스택이 풀리는 동안 유지되어야하며 스레드로부터 안전해야합니다. 따라서 구현시 메모리 부족 조건에서 bad_alloc 예외 발생을 지원 하기 위해 비상 버퍼 를 제공 할 수 있지만 예외 객체 저장소는 일반적으로 힙에 할당됩니다 .
이제 이것은 Itanium ABI 일 뿐이며 GCC, Clang 및 MSVC와 관련된 세부 정보를 찾고 있습니다. 그러나 표준은 아무것도 지정하지 않으며 이것은 예외 저장소를 구현하는 명백한 방법 인 것 같습니다.
이것이 귀하의 질문에 대한 답이 될지 모르겠지만 (C ++ 컴파일러가 예외 처리를 구현하는 방법) 은 예외 처리에 대한 훌륭한 기사입니다. 나는 그것을 적극 추천합니다 (:
짧은 답변에 대해 죄송합니다. 기사의 전체 정보가 훌륭합니다. 여기에서 일부 정보를 선택하여 게시 할 수 없습니다.
excpt_info
해당 페이지에서 검색 하면 MSVC가 수행하는 방법에 대한 정보가 제공됩니다.
글쎄, 그것은 풀릴 것이기 때문에 스택에있을 수 없으며 힙에있을 수도 없습니다 std::bad_alloc
. 시스템이 던질 수 없다는 것을 의미하기 때문입니다 . 그 외에는 구현에 따라 다릅니다. 구현이 지정되지 않았으며 (문서화되어야 함) 지정되지 않았습니다. (더 이상 메모리가없는 경우에도 제한된 수의 예외를 허용하는 일종의 긴급 백업이있는 한 구현에서 대부분의 경우 힙을 사용할 수 있습니다.)
std::bad_alloc
작동 해야 합니다. 이는 구현에서 힙을 체계적으로 사용할 수 없음을 의미합니다. 표준은 그것을 허용하지 않습니다. 나는 내 주장을 표준에 근거하고있다.