рдЬрдм рд╡рд╣ рдпрд╣ рд╡рд┐рд╢реБрджреНрдз рд░реВрдк рд╕реЗ рддрдХрдиреАрдХреА рд▓реЗрдЦ рд▓рд┐рдЦ рд░рд╣рд╛ рдерд╛, рддреЛ рд╣рдмрд░ рдбрдмреНрд▓реНрдпреВрдПрдЪрдУ рдХреЗ рдПрдХ рд╕реНрдерд╛рдиреАрдп рдХрд╛рд░реНрдпрд╛рд▓рдп рдореЗрдВ рдмрджрд▓ рдЧрдпрд╛ рдФрд░ рдЕрдм рдореБрдЭреЗ рдЗрд╕реЗ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рднреА рд╢рд░реНрдо рдЖ рд░рд╣реА рд╣реИ ... рд▓реЗрдХрд┐рди рдЖрддреНрдорд╛ рдореЗрдВ рдпрд╣ рдЖрд╢рд╛ рдЧрд░реНрдо рд╣реИ рдХрд┐ рдЖрдИрдЯреА рдХреЗ рд▓реЛрдЧ рдЕрднреА рддрдХ рдирд╣реАрдВ рднрд╛рдЧреЗ рд╣реИрдВ рдФрд░ рд╡рд╣ рдЕрдкрдиреЗ рдкрд╛рдардХ рдХреЛ рдвреВрдВрдвреЗрдЧрд╛ред рдпрд╛ рдирд╣реАрдВ?
рдореБрдЭреЗ рд╣рдореЗрд╢рд╛ рдорд╛рдирдХ рд╕реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╢рдВрд╕рд╛ рдорд┐рд▓реА, рдФрд░ рд╕реА рдЦреБрдж - рдЕрдкрдиреЗ рд╕рднреА рдЕрддрд┐рд╕реВрдХреНрд╖реНрдорд╡рд╛рдж рдХреЗ рд╕рд╛рде, рдпрд╣ рдЕрднреА рднреА рдЙрди рд▓реЛрдЧреЛрдВ рдХреА рднрд╛рд╡рдирд╛ рдХреЛ рдЙрдбрд╝рд╛ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рдмрд╣реБрдд рд▓рд╛рд▓ рдЖрдВрдЦреЛрдВ рд╣реИрдХрд░ ред рдХрд╛ рдорд╕реМрджрд╛ рдкрд╣рд▓реА рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдорд╛рдирдХ (рдПрдПрдирдПрд╕рдЖрдИ рд╕реА, C89 рдЙрд░реНрдл, рдЙрд░реНрдл рдПрдПрдирдПрд╕ X3.159-1989, рдмрд╛рдж рдореЗрдВ, C90 рдФрд░ рдЖрдИрдИрд╕реА 9899: 1990) 145 рдХрд╛рд░реНрдпреЛрдВ рдФрд░ рдореИрдХреНрд░реЛ рд╣реИ, рдЬреЛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ 25 рдмрджрд▓рд╛рд╡ рд╣реЛрддреЗ рд░рд╣рддреЗ рд╣реИрдВ (рдХреА рдХрдореА рдХреЗ рдХрд╛рд░рдг рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдУрд╡рд░рд▓реЛрдб рдХреА рднрд╛рд╖рд╛ рдореЗрдВ), рдФрд░ 26 рд╡рд┐рд╢реБрджреНрдз рд░реВрдк рд╕реЗ рдЧрдгрд┐рддреАрдп рд╣реИрдВред рдХреЗ рдПрдВрдб рдЖрд░ рдХреЗ рджреВрд╕рд░реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ 114 рдХрд╛рд░реНрдпреЛрдВ (рдкреНрд▓рд╕ рдЧрдгрд┐рддреАрдп) рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдмрд╛рдХреА рдХреЛ рд╡рд┐рджреЗрд╢реА рдорд╛рдирддреЗ рд╣реБрдПред рдореЗрдВ draft┬│ C11 рд╡рд╣рд╛рдБ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА 348 рдХрд╛рд░реНрдпреЛрдВ рд░рд╣реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдХ рд╕реМ рд╕реЗ рдЕрдзрд┐рдХ рдЧрдгрд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ 90 рд╕реЗ рдЕрдзрд┐рдХ рдХрд░ рд░рд╣реЗ рд╣реИрдВ "рднрд╛рд░ рдХреЗ"ред рдЕрдм рдЖрдЗрдП рдмреВрд╕реНрдЯ рдХреЛ рджреЗрдЦреЗрдВ, рдЬрд╣рд╛рдВ рдХреЗрд╡рд▓ 160 рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИрдВ ред рдЪреВрд░ рдореБрдЭреЗтАж
рдФрд░ рдпрд╣ рд╕реМ рдФрд░ рдПрдХ рдЖрдзреЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд╡рд╣рд╛рдБ рд╣рдореЗрд╢рд╛ рдереЗ: рд╕рд┐рдЧреНрдирд▓ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ, рдкрд░рд┐рд╡рд░реНрддрди рд╕рдВрдмрдВрдзреА рдХрд╛рд░реНрдп (рдЬреЛ рдкреАрдПрдЪрдкреА 25 рд╕рд╛рд▓ рдмрд╛рдж рд╡реНрдпрд╛рдЦреНрдпрд╛ рдкрд╣реБрдВрдЪ рдЧрдпрд╛, рдФрд░ рдбреЗрд▓реНрдлреА, рдореЗрдВ рдЬреЛ рдПрдХ рд╕рдордп рдореЗрдВ рдлрд▓рдлреВрд▓ рд░рд╣рд╛ рдерд╛, рд╡реЗ рдЕрднреА рднреА рдпрд╛рдж рдХрд░ рд░рд╣реЗ рд╣реИрдВ) рдФрд░ рдЗрд╕ рддрд░рд╣ 50 рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ printf () ( mmm ... рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ), рд╕реНрдЯреНрд░реИрдлрд╝рдЯрд╛рдЗрдо () (...) рдФрд░ рд╕реНрдХреИрдирдлрд╝ () (рд░реЗрдЧреБрд▓рд░ рдХрд╛ рд╕рд╕реНрддрд╛ рд╡рд┐рдХрд▓реНрдк)ред
рдФрд░ рд╣рдореЗрд╢рд╛ рд╕реЗрдЯрдЬрдореНрдк () / рд▓реЙрдиреНрдЧрдЬрдореНрдк () рд╣реЛрддрд╛ рд╣реИ , рдЬреЛ рдЖрдкрдХреЛ рдкреЛрд░реНрдЯреЗрдмрд▓ рд╕реА рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдкрд░реЗ рдЬрд╛рдП рдмрд┐рдирд╛ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдкрд░рд┐рдЪрд┐рдд рдЕрдкрд╡рд╛рдж рддрдВрддреНрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдЧрдИ рд╣реИ - рдХреНрд╡реЗрдХ рд╡рд░реНрд▓реНрдб , рд╕реНрдЯреИрдХ, рд░рдЬрд┐рд╕реНрдЯрд░, рдЕрд╕реЗрдореНрдмрд▓рд░реНрд╕ рдФрд░ рдЕрдиреНрдп рдореИрдЯрд░рд┐рдпрд▓ , рдФрд░ рдЪреЗрд░реА рдПрдХ рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рдЖрдБрдХрдбрд╝рд╛ рд╣реИ ( рд╕реНрдкреЙрдЗрд▓рд░ : рд╡рд┐рдЬрд╝реБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ рдирд┐рд░рдВрддрд░ рдирд╣реАрдВ рд╣реИ, рдорд╛рд░реНрдЪ рд╣реИрд░реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдФрд░ рд╕рднреА рдХреЗ рдЖрдзреЗ рд╕рдордп рдореЗрдВ рдлреЗрдВрдХ рджреЗрддреЗ рд╣реИрдВ saneex.c
)ред

рдЫрд┐рдкрд╛ рд╣реБрдЖ рдкрд╛рда┬╣ .
┬▓ , . 270 , 80 тАФ . , . K&R тАФ , .
┬│ , ANSI ISO , . .
тБ┤ , ┬л┬╗ TinyURL, URL , ╤Ц . , -. urlex.org.
рд╡рд┐рд╖рдп - рд╕реВрдЪреА:
, тАФ setjmp()/longjmp(), setjmp.h, ┬лSJLJ┬╗ ( , ). C89 , -, , ( тАФ , тАФ ).
, , , zzeng. , , , ┬╣, , , ( , ), .
┬╣ CException тАФ 60 , , , ANSI C, finally , .
, тАФ , , , , , ┬л ┬╗. (, , - ┬л┬╗ , errno . тАФ , .)
, :
- , - , ( , тАФ ,
if (error) return -1;
) - - тАФ , ,
. , .
setjmp()/longjmp()
, longjmp() тАФ goto, setjmp() тАФ goto run-time. , ┬лgoto ┬╗. , , , goto, тАФ , goto . , - , ( тАФ ┬лtry┬╗).
, , , , setjmp.h
^W ? , setjmp() , (, , ). , , , . .
, , setjmp() тАФ fork() POSIX . , *nixтАЩ API WinAPI, тАФ , . тАФ ┬л , ?┬╗тАж .
, , тАФ , () . тАФ ( IntelтАЩ тАФ ), тАФ ( IntelтАЩ тАФ -, ). :
void sub(int s) {
char buf[256];
sub(2);
}
int main(int m) {
sub(1);
}
тАФ tcc (Tiny C Compiler) - . . tcc . sub() ( Intel, ):
sub esp, 100h ;
mov eax, 2 ;
push eax
call sub_401000 ; sub()
add esp, 4 ; (= cdecl)
:

тАФ ( IntelтАж , ). ESP (RSP x86_64). setjmp() ESP/RSP, , jmp_buf, . longjmp() ( ) тАФ , , setjmp(), (). , ┬лundo┬╗ (, ).
setjmp() jmp FEF8h
(FDF0h
.. тАФ ) , :
void sub(int s) {
char buf[256];
jmp_buf jmp;
setjmp(jmp);
sub(2);
}
, , тДв:
- тАФ , , ! тАФ , , , setjmp() , longjmp() , setjmp()
, -, clobbering
. :
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
int main(void) {
int i;
jmp_buf jmp;
i = rand();
if (setjmp(jmp) == 0) {
i = rand();
printf("%d\n", i);
longjmp(jmp, 1);
} else {
printf("%d\n", i);
}
}
: ?
: . -!
, gcc. -O0, , :
; int main(void) {
push ebp ; ( stack frame)
mov ebp, esp ; EBP ESP ( )
sub esp, E0h
...
call _rand ; EAX
mov [ebp-D4h], eax ; i = rand(); i (EBP-D4h)
...
; if (... == 0) { ; setjmp()
call _rand
mov [ebp-D4h], eax ; i = rand();
; printf("%d\n", i);
mov eax, [ebp-D4h] ; i
mov esi, eax
lea edi, format ; "%d\n"
mov eax, 0
call _printf
...
; } else { ; setjmp()
mov eax, [ebp-D4h] ; i,
mov esi, eax
lea edi, format ; "%d\n"
mov eax, 0
call _printf
, i ( EBP - D4h
). , :
- 256 char int jmp_buf, 4 200 , 20 - , 224 (E0h) 100h,
- ESP setjmp()
FFF8h - E0h = FF18h
( FEF8h
), jmp
- i, i (
FF18h
) - longjmp()
FF18h
, , i , - , (jmp), main() ( )
-O1, :
; stack frame , ESP
sub esp, E8h
...
call _rand
mov [esp+E8h-DCh], eax ; i = rand(); , -O0
...
; -O1 - , else ,
; if (setjmp() == 0) ( - ),
; ;
; if (... == 0) {
call _rand
mov esi, eax ; ! i
; printf("%d\n", i);
lea edi, format ; "%d\n"
mov eax, 0
call _printf
...
; } else {
mov esi, [esp+E8h-DCh] ; ! i
lea edi, format ; "%d\n"
mov eax, 0
call _printf
, -O1 gcc :
test.c:6:11: warning: variable тАШiтАЩ might be clobbered by тАШlongjmpтАЩ or тАШvforkтАЩ [-Wclobbered]
? i , ( if) gcc, i printf(), ESI, ( ESI printf(), . ABI, . 22 тАФ RDI (format), RSI (i), тАж). - :
ESP + E8h - DCh
rand()- ESI
- printf() ( ) ()
- longjmp() , ,
- printf() ( else) , , ,
- ESI, (, printf() longjmp())
, :
stack[i] = rand(); // i = rand(); (1)
if (setjmp(jmp) == 0) {
ESI = rand(); // i = rand(); (2)
printf("%d\n", ESI); // (2)
longjmp(jmp, 1); //
} else {
printf("%d\n", stack[i]); // (1)
// :
printf("%d\n", ESI); // , -
// "" ( printf() longjmp())
}
, , gcc rand() ESI ( -O3). SO , x86_64 ( ) , EAX. ? , gcc printf() else longjmp(), rand() printf() тАФ , i .
тАФ .
volatile
┬л ┬╗ тАФ volatile ( тАФ ┬л┬╗). , , , :
volatile int i;
-O1 if:
; :
call _rand
mov esi, eax
; :
call _rand
mov [rsp+E8h-DCh], eax
mov esi, [rsp+E8h-DCh]
; :
call _rand
mov esi, eax
mov [rsp+E8h-DCh], eax
, ():
if (setjmp(jmp) == 0) {
ESI = stack[i] = rand();
IRL
, тАФ -volatile , SJLJ . тАФ , SJLJ :
, , тАФ , ┬л ┬╗, , , - (). , DrMefistO.
Quake World WinMain(), jmp_buf, , ┬л continue┬╗:
// WinQuake/host.c
jmp_buf host_abortserver;
void Host_EndGame (char *message, ...)
{
...
if (cls.demonum != -1)
CL_NextDemo ();
else
CL_Disconnect ();
longjmp (host_abortserver, 1);
}
void Host_Error (char *error, ...)
{
...
if (cls.state == ca_dedicated)
Sys_Error ("Host_Error: %s\n",string); // dedicated servers exit
CL_Disconnect ();
cls.demonum = -1;
inerror = false;
longjmp (host_abortserver, 1);
}
void _Host_Frame (float time)
{
static double time1 = 0;
static double time2 = 0;
static double time3 = 0;
int pass1, pass2, pass3;
if (setjmp (host_abortserver) )
return; // something bad happened, or the server disconnected
...
}
// QW/client/sys_win.c
int WINAPI WinMain (...)
{
...
while (1)
{
...
newtime = Sys_DoubleTime ();
time = newtime - oldtime;
Host_Frame (time);
oldtime = newtime;
}
/* return success of application */
return TRUE;
}
, тАФ . , setjmp() glibc , . :
- , , SJLJ/
saneex.c
- -тАж- (
, ) , - тАФ , - , тАФ zero-cost exceptions (, , zero-cost try), try, () тАФ goto , , , ┬л┬╗ , -,
┬л┬╗ zero-cost exceptions , volatile-, , ( longjmp()). , :
, saneex.c
zero-cost ( тАФ ), setjmp(), ? , ? тАФ .
┬л ┬╗, main() 100 try/catch throw().
C:
#include <stdio.h>
#include <time.h>
#include "saneex.h"
int main(void) {
for (int i = 0; i < 100000; i++) {
try {
// ("" = ):
throw(msgex("A quick fox jumped over a red dog and a nyancat was spawned"));
// ("" = ):
time(NULL);
} catchall {
fprintf(stderr, "%s\n", curex().message);
} endtry
}
}
++ ( , cerr <<
fprintf()):
#include <iostream>
#include <vector>
#include <stdexcept>
#include <time.h>
int main() {
std::vector<int> vec{ 3, 4, 3, 1 };
for (int i = 0; i < 100000; i++) {
try {
// ("" = ):
int i{ vec.at(4) };
// ("" = ):
time(NULL);
}
catch (std::out_of_range & e) {
// << fprintf() 25-50%
//std::cerr << "Accessing a non-existent element: " << e.what() << '\n';
fprintf(stderr, "%s\n", e.what());
}
catch (std::exception & e) {
//std::cerr << "Exception thrown: " << e.what() << '\n';
fprintf(stderr, "%s\n", e.what());
}
catch (...) {
//std::cerr << "Some fatal error\n";
fprintf(stderr, "Some fatal error");
}
}
return 0;
}
( 64-):
- Windows 10 2019 LTSC PowerShell
Measure-Command { test.exe 2>$null }
- Live CD Ubuntu time
Windows __try/__except, :
#include <windows.h>
#include <stdio.h>
#include <vector>
int filterExpression(EXCEPTION_POINTERS* ep) {
ep->ContextRecord->Eip += 8;
return EXCEPTION_EXECUTE_HANDLER;
}
int main() {
static int zero;
for (int i = 0; i < 100000; i++) {
__try {
zero = 1 / zero;
__asm {
nop
nop
nop
nop
nop
nop
nop
}
printf("Past the exception.\n");
}
__except (filterExpression(GetExceptionInformation())) {
printf("Handler called.\n");
}
}
}
тАФ , :
error C2712: Cannot use __try in functions that require object unwinding
, , . 1100-1300 (Debug Release, x86) тАФ , VS, , g++.
тДЦ ()┬╣ saneex
1. VS 2019 v16.0.0 Debug x64 saneex.c 9713 / 8728 = 1.1 1.8 / 1.8
2. VS 2019 v16.0.0 Debug x64 saneex.c 95 / 46 = 2 4.5 / 2.3
3. VS 2019 v16.0.0 Debug x64 C++ 5449 / 4750┬▓ = 1.6
4. VS 2019 v16.0.0 Debug x64 C++ 21 / 20 = 1
5. VS 2019 v16.0.0 Release x64 saneex.c 8542┬│ / 182 = 47 1.8 / 0.4
6. VS 2019 v16.0.0 Release x64 saneex.c 80┬│ / 23 = 3.5 8 / 1.8
7. VS 2019 v16.0.0 Release x64 C++ 4669┬│ / 420 = 11
8. VS 2019 v16.0.0 Release x64 C++ 10┬│ / 13 = 0.8
9. gcc 9.2.1 -O0 x64 saneex.c 71 / 351 = 0.2 0.2 / 0.6
10. gcc 9.2.1 -O0 x64 saneex.c 6 / 39 = 0.2 1.5 / 1.1
11. g++ 9.2.1 -O0 x64 C++ 378 / 630 = 0.6
12. g++ 9.2.1 -O0 x64 C++ 4 / 37 = 0.1
13. gcc 9.2.1 -O3 x64 saneex.c 66 / 360 = 0.2 0.2 / 0.6
14. gcc 9.2.1 -O3 x64 saneex.c 5 / 23 = 0.2 1 / 0.6
15. g++ 9.2.1 -O3 x64 C++ 356 / 605 = 0.6
16. g++ 9.2.1 -O3 x64 C++ 5 / 38 = 0.1
┬╣ Windows 7 SP1 x64 VS 2017 v15.9.17 gcc cygwin.
┬▓ : fprintf() cerr <<
, 3 : 1386/1527 .
┬│ VS , .
тАж :
- / ┬л┬╗ VS. тАФ .
cerr <<
fprintf() VS 3-4 ( 3). ?- try throw тАФ (4-28 100 ).
- ┬л┬╗ Debug VS,
saneex.c
, ( 2.3 VS, 5 gcc/g++), try throw тАФ , . !
тАж . !
use-case тАФ try throw (┬л , ┬╗), setjmp(), , , , . , , setjmp() OpenBSD (1.45) тАФ Solaris. 2005 . ┬л┬╗ тАФ , .
, тАж
тАФ saneex.c
, :
- Visual Studio
- , throw() , finally catch ( )
- ( static)
- - (__thread/_Thread_local)
- public domain (CC0)
GitHub. , . saneex-demo.c
:
01. #include <stdio.h>
02. #include "saneex.h"
03.
04. int main(void) {
05. sxTag = "SaneC's Exceptions Demo";
06.
07. try {
08. printf("Enter a message to fail with: [] [1] [2] [!] ");
09.
10. char msg[50];
11. thrif(!fgets(msg, sizeof(msg), stdin), "fgets() error");
12.
13. int i = strlen(msg) - 1;
14. while (i >= 0 && msg[i] <= ' ') { msg[i--] = 0; }
15.
16. if (msg[0]) {
17. errno = atoi(msg);
18. struct SxTraceEntry e = newex();
19. e = sxprintf(e, "Your message: %s", msg);
20. e.uncatchable = msg[0] == '!';
21. throw(e);
22. }
23.
24. puts("End of try body");
25.
26. } catch (1) {
27. puts("Caught in catch (1)");
28. sxPrintTrace();
29.
30. } catch (2) {
31. puts("Caught in catch (2)");
32. errno = 123;
33. rethrow(msgex("calling rethrow() with code 123"));
34.
35. } catchall {
36. printf("Caught in catchall, message is: %s\n", curex().message);
37.
38. } finally {
39. puts("Now in finally");
40.
41. } endtry
42.
43. puts("End of main()");
44. }
, :
End of try body
Now in finally
End of main()
- , , (1),
catch (1)
(26.), :
Caught in catch (1)
Your message: 1 hello, habr!
...at saneex-demo.c:18, code 1
Now in finally
End of main()
Caught in catch (2)
Now in finally
Uncaught exception (code 123) - terminating. Tag: SaneC's Exceptions Demo
Your message: 2 TM! kak tam blok4ain?
...at saneex-demo.c:18, code 2
calling rethrow() with code 123
...at saneex-demo.c:33, code 123
rethrown by ENDTRY
...at saneex-demo.c:41, code 123
!
, ┬л┬╗ (uncatchable; 20.) тАФ try , ( catch, finally), тАФ abort():
Caught in catch (1)
Your message: ! it is a good day to die
...UNCATCHABLE at saneex-demo.c:18, code 0
Now in finally
Uncaught exception (code 0) - terminating. Tag: SaneC's Exceptions Demo
Your message: ! it is a good day to die
...UNCATCHABLE at saneex-demo.c:18, code 0
UNCATCHABLE rethrown by ENDTRY
...at saneex-demo.c:41, code 0
Caught in catchall, message is: Your message: 3 we need more gold
Now in finally
End of main()
┬л┬╗
. , ( MSVC┬╣), C11 (TLS):
#define SX_THREAD_LOCAL _Thread_local
┬╣ Microsoft - open source, , , 8 , .
sxTag (05.) тАФ , stderr. тАФ (__DATE__ __TIME__).
SxTraceEntry ( stack trace). тАФ (struct SxTraceEntry) {...}
:
newex()
тАФ ; __FILE__, __LINE__ = errno ( , fgets(); 11.)
- 1 1 ( setjmp() 0 ),
catch (0)
msgex(m)
тАФ newex(), ( )exex(m, e)
тАФ msgex(), ; free() :
try {
TimeoutException *e = malloc(sizeof(*e));
e->elapsed = timeElapsed;
e->limit = MAX_TIMEOUT;
errno = 146;
throw(exex("Connection timed out", e));
} catch (146) {
printf("%s after %d\n", curex().message,
// void *SxTraceEntry.extra:
((TimeoutException *) curex().extra)->elapsed);
} endtry
, , designated initializers C99 ( Visual Studio 2013+):
throw( (struct SxTraceEntry) {.message = "kaboom!"} );
:
throw(e)
тАФ SxTraceEntryrethrow(e)
тАФ throw(), stack trace; catch/catchallthrif(x, m)
тАФ ; if (x)
SxTraceEntry x + m ┬л┬╗thri(x)
тАФ thrif(), m
┬л┬╗ тАФ fgets() (11.), . fgets() ( EOF: ./a.out </dev/null
), . :
thri(read(0xBaaD, buf, nbyte));
// errno = 9, "Bad file descriptor"
// Assertion error: read(0xBaaD, buf, nbyte);
тАж ┬л ┬╗
( !):
- endtry тАФ ( try)
- return try endtry тАФ , ; PR
┬л┬╗, volatile. ┬л┬╗ тАФ (. longjmp()), , try, catch/catchall/finally endtry, volatile. . :
int foo = 1;
try {
foo = 2;
// foo
} catchall {
// !
} finally {
// !
} endtry
// !
volatile :
volatile int foo = 1;
try {
...
:
- () :
struct SxTryContext
тАФ try, тАФ , jmp_buf ; , :
try {
try {
//
} endtry
} endtry
struct SxTraceEntry
тАФ stack trace, , ; , try:
try { // SxTryContext
try { // SxTryContext
// SxTraceEntry
throw(msgex(" !"));
// SxTraceEntry
} catchall {
// SxTraceEntry
rethrow(msgex(" !"));
// SxTraceEntry (*)
} endtry
} endtry
rethrow() throw(), SxTraceEntry (*)
, тАФ (stack trace ). , sxAddTraceEntry(e)
.
рдХреЛрд╢рд┐рд╢ рдХрд░реЛ рдФрд░ рдЕрдиреНрдп рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рддрддреНрд╡ рдореИрдХреНрд░реЛрдЬрд╝ (- рдЖрдкрдХреЗ рдХреЗрдУ ) рд╣реИрдВред { }
рдЙрдирдХреЗ рдмрд╛рдж рдмреНрд░реИрдХреЗрдЯ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реИрдВред рдЕрдВрдд рдореЗрдВ, рдпрд╣ рд╕рднреА рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЫрджреНрдо рдХреЛрдб рдХреЛ рдЙрдмрд╛рд▓рддрд╛ рд╣реИ:
try { int _sxLastJumpCode = setjmp(add_context()┬╣);
bool handled = false;
if (_sxLastJumpCode == 0) {
throw(msgex("Mama mia!")); clearTrace();
sxAddTraceEntry(msgex(...));
if (count_contexts() == 0) {
fprintf(stderr, "Shurik, vs propalo!");
sxPrintTrace();
exit(curex().code);
} else {
longjmp(top_context());
}
} catch (9000) { } else if (_sxLastJumpCode == 9000) {
handled = true;
} catchall { } else {
handled = true;
} finally { }
// finally { }
} endtry remove_context();
if (!handled) {
// throw()
}
┬╣ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ _ рдХреЗ рд╕рд╛рде рдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╡реЗ рд╕рд╛рд░ рд╣реИрдВред
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, рдПрд╕рдЬреЗрдПрд▓рдЬреЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдХреА рд╡рд┐рд╕реНрддреГрдд рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХреЗ рдмрд╛рдж , рдпрд╣рд╛рдБ рдЯрд┐рдкреНрдкрдгреА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдФрд░ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдЫреБрдЯреНрдЯреА рд▓реЗрдиреЗ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЖрдкрдХреЛ рдордВрдЬрд┐рд▓ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред