top of page

Stramosii exceptiilor

Nu stiu cati dintre cei ce cititi acest blog, scrieti in limbaje de nivel inalt. Ma gandesc ca multi, data fiind popularitatea si diversitatea acestor limbaje. Totodata, cati v-ati pus intrebarea, in momentul in care folositi o clauza de tip throw/try - catch a exceptiilor, ce se intampla in spate?

Sper ca prin intermediul acestui articol, sa fac mai multa lumina asupra mecanismului, respectiv de unde s-a nascut el.


#include "setjmp.h"

Standardul de ANSI C include o suita de biblioteci (libc) optimizate si revizuite, care ne fac viata mai usoara cand scriem cod.

Printre aceste biblioteci, este inclusa si "setjmp.h". Desi in facultate se foloseste des "stdio.h"(ex: printf), "stdlib.h"(ex: malloc), "string.h"(ex: strcpy, strcmp, memcpy), "math.h"(ex: sqrt) samd, nu am avut niciodata ocazia sa folosesc facilitati ale "setjmp.h", pana de curand.

Biblioteca este accesibila in gcc si implicit in toate compilatoarele. Pe distributiile de Linux, de regula veti gasi headerul la "/usr/include/sys" sau "/usr/include".

Sumaristic, continutul este urmatorul:

  • un tip de date: jmp_buf - acesta este definit ca un vector de un anumit tip si o anumita dimensiune, specifice arhitecturii procesorului

  • un macro: setjmp(env) - se expandeaza la int setjmp (jmp_buf __JBF)

  • o functie: void longjmp(jmp_buf __JBF, int __RET_VAL)


How it works

Intr-un mod explicat cat mai simplist, setjmp va stoca o serie de registrii printre care si Program Counterul(PC) - totul depinde de arhitectura - , va returna 0 si va permite procesorului sa continue executia instructiunilor, pana la intalnirea lui longjmp care intoarce valoarea dorita de noi.

Poate va intrebati, concret, cu ce ne ajuta acest mecanism?

Asemenea clauzelor throw/try - catch, dispunem de o unealta foarte puternica prin care putem sa sporim controlul asupra situatiilor nedorite. Cateva exemple:

  • am alocat o bucata de memorie mai mult decat trebuia

  • codul a luat-o razna si a ajuns intr-o sectiune nedorita

  • am dereferentiat un pointer indicand o adresa invalida

  • etc

Evident, scopul final este acela de a remedia o functionare incorecta a codului.


Concret...

Consideram urmatorul fisier sursa:

/* Prj.c - Init components and perform calculations */

#include "setjmp.h"


enum En_InitStatus {

INIT_OK = 0,

INIT_NOT_OK

};


#define INT_SIZE ((sizeof(int))


int *Prj_ArrayOfInts;

En_InitStatus Prj_InitStatus;

jmp_buf JumpStoreBuffer;


En_InitStatus Prj_Init(int **tmp_IntArrToInit, int size)

{

/* status de returnat */

En_InitStatus tmp_RetInitStatus;


if(0 == setjmp(JumpStoreBuffer))

{

*tmp_arrayToInit = (int *)malloc(size * INT_SIZE));

}

else if(1==setjmp(JumpStoreBuffer))

{

printf("Data allocation failed");

Prj_Realloc(*tmp_IntArrToInit);

}

else

{

printf("Data allocation failed");

Prj_MemoryRefresh(*tmp_IntArrToInit);

Prj_EnterErrorMode();

}


/* perform rest of initialization */

[...]


return tmp_RetInitStatus;

}



static int Prj_CalcAverage(int **tmp_InputArray, int size)

{

int tmp_ReturnAverage;

if(INIT_NOT_OK == Prj_InitStatus)

{

longjmp(JumpStoreBuffer,255);

}

else if(NULL == *tmp_InputArray)

{

longjmp(JumpStoreBuffer, 1);

}

else

{

tmp_ReturnAverage = Prj_MovingAverage(*tmp_InputArray, int size);

}

}



Cum o poza spune cat 1000 de cuvinte:

Concluzia

Sunt mai multe mecanisme similare ca cel prezentat de fata, cum ar fi in embedded automotive DETul, cod aditional care sa "prinda" astfel de probleme, setare de exceptii samd, insa toate acestea au o lacuna si anume imposibilitatea efectuarii unui jump indirect fara a mai procesa mult cod aditional.


Voi unde gasiti utila folosirea acestei biblioteci?


Criticile si comentariile sunt apreciate.





49 afișări0 comentarii

Postări recente

Afișează-le pe toate

Calea catre main() - intro

In liceu am invatat ca un program incepe de la main(), acest lucru fiind valabil in mai multe limbaje de uz intens. De ce main()? Ce-i...

Comments


bottom of page