Development Tip

내부적으로 예외는 어떻게 구현됩니까?

yourdevel 2020. 11. 24. 19:59
반응형

내부적으로 예외는 어떻게 구현됩니까?


거의 모든 사람들이 그것들을 사용하지만 저를 포함한 많은 사람들이 단순히 작동한다는 것을 당연시합니다.

고품질 소재를 찾고 있습니다. 내가 사용하는 언어는 Java, C, C #, Python, C ++이므로 가장 흥미 롭습니다.

이제 C ++는 해당 언어로 무엇이든 던질 수 있기 때문에 시작하기에 좋은 곳일 것입니다.

또한 C는 어셈블리에 가깝습니다. 순수한 C 구조를 사용하고 어셈블리를 사용하지 않고 예외를 어떻게 에뮬레이션합니까?

마지막으로 Google 직원이 속도를 고려하여 일부 프로젝트에 예외를 사용하지 않는다는 소문을 들었습니다. 이것은 단지 소문입니까? 그것들없이 어떻게 실질적인 것을 성취 할 수 있습니까?

감사합니다.


예외는 고급 비-로컬 흐름 제어 구조의보다 일반적인 경우의 특정 예일뿐입니다. 다른 예는 다음과 같습니다.

  • 알림 (예 : CommonLisp 및 Ioke에서 구현 된 일부 오래된 Lisp 개체 시스템에서 원래 예외의 일반화)
  • 연속 ( GOTO고급, 고차원 언어에서 널리 사용 되는보다 구조화 된 형태의 ),
  • 코 루틴 (특히 Lua에서 인기있는 서브 루틴의 일반화),
  • Python의 생성기 (본질적으로 제한된 형태의 코 루틴),
  • 섬유 (협동 경량 실) 및 물론 이미 언급 한
  • GOTO.

(내가 놓친 다른 많은 것이 있다고 확신합니다.)

이 구조의 흥미로운 특성은 표현력이 거의 동일하다는 것입니다. 하나 가 있으면 다른 모든 구조를 매우 쉽게 만들 수 있습니다.

따라서 예외를 가장 잘 구현하는 방법은 사용 가능한 다른 구성에 따라 다릅니다.

  • 모든 CPU에는 GOTO이 있으므로 필요한 경우 언제든지 그 상태로 되돌릴 수 있습니다.
  • C는이 setjmp/ longjmp맥가이버의 연속성을 기본적으로있는 (덕트 테이프와 이쑤시개, 꽤 진짜의 내장,하지만 당신이 뭔가 더 사용할 수없는 경우 적어도 즉시 문제의 당신을 얻을 것이다).
  • JVM과 CLI에는 자체 예외가 있습니다. 즉, 언어의 예외 의미가 Java / C #과 일치하면 집에서 자유 로워집니다 (그렇지 않으면 망가집니다).
  • 예외 및 연속으로서의 Parrot VM.
  • Windows에는 예외 처리를위한 자체 프레임 워크가 있으며, 언어 구현자가 자체 예외를 작성하는 데 사용할 수 있습니다.

, 모두의 매우 흥미로운 사용 사례 사용 예외 구현 예외는 마이크로 소프트 라이브 랩의 볼타 프로젝트입니다. (현재는 사라졌습니다.) Volta의 목표는 버튼 하나만 누르면 웹 애플리케이션을위한 아키텍처 리팩토링을 제공하는 것이 었습니다. 따라서 .NET 코드에 일부 [Browser]또는 [DB]특성을 추가하는 것만으로 1 계층 웹 애플리케이션을 2 계층 또는 3 계층 애플리케이션으로 전환 할 수 있으며, 그러면 코드가 클라이언트 또는 DB에서 자동으로 실행됩니다. 그러기 위해서는 .NET 코드를 JavaScript 소스 코드로 변환해야했습니다.

지금, 당신은 할 수 단지 자바 스크립트에서 전체 VM을 작성하고 수정되지 않은 바이트 코드를 실행합니다. (기본적으로 CLR을 C ++에서 JavaScript로 포팅합니다.) 실제로이 작업을 수행하는 프로젝트 (예 : HotRuby VM)가 있지만 이것은 비효율적이며 다른 JavaScript 코드와 상호 운용성이 매우 낮습니다.

그래서 대신 그들은 CIL 바이트 코드를 자바 스크립트 소스 코드로 컴파일하는 컴파일러를 작성했습니다. 그러나 JavaScript에는 .NET에있는 특정 기능 (생성자, 스레드, 두 가지 예외 모델이 100 % 호환되지 않음)이 부족하고, 더 중요한 것은 컴파일러 작성자가 좋아하는 ( GOTO또는 연속) 사용 가능한 특정 기능이 없다는 것입니다. 위에서 언급 한 누락 된 기능을 구현합니다.

그러나 JavaScript 에는 예외 있습니다. 그래서, 그들이 사용하는 자바 스크립트 예외를 구현하는 볼타 Continuations를을 하고는 사용 볼타 Continuations를을 구현하는 .NET 예외 , .NET 발생기 , 심지어 .NET 관리 스레드 (!)

따라서 원래 질문에 답하려면 :

내부적으로 예외는 어떻게 구현됩니까?

예외로 아이러니하게도! 어쨌든이 아주 특정한 경우에는.

또 다른 좋은 예는 Go 메일 링리스트에있는 예외 제안 중 일부로, Goroutines를 사용하여 예외를 구현합니다 (동시 코 루틴과 CSP 프로세스의 혼합과 같은 것). 또 다른 예는 하스켈로, 예외를 구현하기 위해 Monads, 지연 평가, 꼬리 호출 최적화 및 고차 함수를 사용합니다. 일부 최신 CPU는 예외에 대한 기본 구성 요소 (예 : Azul Systems Java Compute Accelerator 용으로 특별히 설계된 Vega-3 CPU)도 지원합니다.


다음은 C ++ 예외를 구현하는 일반적인 방법입니다.
http://www.codesourcery.com/public/cxx-abi/abi-eh.html

Itanium 아키텍처 용이지만 여기에 설명 된 구현은 다른 아키텍처에서도 사용됩니다. C ++ 예외는 복잡하기 때문에 긴 문서입니다.

다음은 LLVM이 예외를 구현하는 방법에 대한 좋은 설명입니다.
http://llvm.org/docs/ExceptionHandling.html

LLVM은 많은 런타임에 대한 일반적인 중간 표현을 의미하므로 설명 된 메커니즘은 여러 언어에 적용될 수 있습니다.


그의 저서 C Interfaces and Implementations : Techniques for Creating Reusable Software 에서 DR Hanson은 일련의 매크로 및 setjmp/longjmp. 그는 C ++ 예외가 수행하는 거의 모든 것을 에뮬레이트 할 수있는 TRY / RAISE / EXCEPT / FINALLY 매크로를 제공합니다.

코드는 정독 할 수있다 여기에 (except.h / except.c에서보고).

추신 : Google에 대한 귀하의 질문입니다. 직원들은 실제로 새 코드에서 예외를 사용할 수 있으며, 이전 코드에서 금지 된 공식적인 이유는 이미 그렇게 작성되었고 스타일을 혼합하는 것이 합리적이지 않기 때문입니다.

개인적으로도 예외가없는 C ++가 최선의 생각이 아니라고 생각합니다.


C / C ++ 컴파일러는 예외 처리를 위해 기본 OS 기능을 사용합니다. .Net 또는 Java와 같은 프레임 워크도 VM에서 OS 기능에 의존합니다. 예를 들어 Windows에서는 구조적 예외 처리 인프라 인 SEH가 실제 무거운 작업을 수행합니다. 이전 참조 기사 인 A Crash Course on the Depths of Win32 ™ Structured Exception Handling을 반드시 읽어야합니다 .

As for the cost of not using exceptions, they are expensive but compared to what? Compared to return error codes? After you factor in the cost of correctness and the quality of code, exceptions will always win for commercial applications. Short of few very critical OS level functions, exceptions are always better overall.

An last but not least there is the anti-pattern of using exceptions for flow control. Exceptions should be exceptional and code that abuses exceptions fro flow control will pay the price in performance.


The best paper ever written on the implementation of exceptions (under the hood) is Exception Handling in CLU by Barbara Liskov and Alan Snyder. I have referred to it every time I've started a new compiler.

For a somewhat higher-level view of an implementation in C using setjmp and longjmp, I recommend Dave Hanson's C Interfaces and Implementations (like Eli Bendersky).


The key thing an exception implementation needs to handle is how to return to the exception handler once an exception has been thrown. Since you may have made an arbitrary number of nested function calls since the try statement in C++, it must unwind the call stack searching for the handler. However implemented, this must incur the code size cost of maintaining sufficient information in order to perform this operation (and generally means a table of data for calls that can take exceptions). It also means that the dynamic code execution path will be longer than simply returning from functions calls (which is a fairly inexpensive operation on most platforms). There may be other costs as well depending on the implementation.

The relative cost will vary depending on the language used. The higher-level language used, the less likely the code size cost will matter, and the information may be retained regardless of whether exceptions are used.

An application where the use of exceptions (and C++ in general) is often avoided for good reasons is embedded firmware. In typical small bare metal or RTOS platforms, you might have 1MB of code space, or 64K, or even smaller. Some platforms are so small, even C is not practical to use. In this kind of environment, the size impact is relevant because of the cost mentioned above. It also impacts the standard library itself. Embedded toolchain vendors will often produce a library without exception capability, which has a huge impact on code size. Highly optimizing compilers may also analyze the callgraph and optimize away needed call frame information for the unwind operation for considerable space reduction. Exceptions also make it more difficult to analyze hard real-time requirements.

In more typical environments, the code size cost is almost certainly irrelevant and the performance factor is likely key. Whether you use them will depend on your performance requirements and how you want to use them. Using exceptions in non-exceptional cases can make an elegant design, but at a performance cost that may be unacceptable for high performance systems. Implementations and relative cost will vary by platform and compiler, so the best way to truly understand if exceptions are a problem is to analyze your own code's performance.


setjmp() and longjmp() usually.

Exception catching does have a non-trivial cost, but for most purposes it's not a big deal.


C++ code at Google (save for some Windows-specific cases) don't use exceptions: cfr the guidelines, short form: "We do not use C++ exceptions". Quoting from the discussion (hit the arrow to expand on the URL):

Our advice against using exceptions is not predicated on philosophical or moral grounds, but practical ones. Because we'd like to use our open-source projects at Google and it's difficult to do so if those projects use exceptions, we need to advise against exceptions in Google open-source projects as well. Things would probably be different if we had to do it all over again from scratch.

This rule does not apply to Google code in other languages, such as Java and Python.


Regarding performance - sparse use of exceptions will probably have negligible effects, but do not abuse them.

I have personally seen Java code which performed two orders of magnitude worse than it could have (took about x100 the time) because exceptions were used in an important loop instead of more standard if/returns.


Some runtimes like the Objective-C runtime have zero-cost 64-bit exceptions. What that means is that it doesn't cost anything to enter a try block. However, this is quite costly when the exception is thrown. This follows the paradigm of "optimize for the average case" - exceptions are meant to be exceptional, so it is better to make the case when there are no exceptions really fast, even if it comes at the cost of significantly slower exceptions.

참고URL : https://stackoverflow.com/questions/1995734/how-are-exceptions-implemented-under-the-hood

반응형