09 października 2019

Programowanie wskaźnikami, wydobycie ukrytej stałej

Oto krótki programik w C++
1. #include <cstdio>
2. const char * const pp=0;
3. const char * pwsk[8];

4. void tekst() {
5.   char s[6] = "Hello";
6.   pwsk[0] = pp+6;
7.   for( int i=0; i<6; i++ ) pwsk[i+1] = pp+s[i];
8.   s[0] = 0;
    };

9. void main( void ) {
10.  tekst();
11.  //printf("%s\n\r", s);
12.   int j = (int) pwsk[0];
13.   for( int i=1; i<j+1; i++ ) printf("%c", pwsk[i]);
14.   printf(" (!)\n\r");
    };

Czy on coś robi? I jest zaskoczenie. Robi! Linia 11. podkreśla, że napis s jest niedostępny, jak powinno być. W końcu jest zmienną (stałą) prywatną funkcji. Tylko dziwnie zachowuje się tablica wskaźników w liniach 7 oraz 13. Nie powinno się tak odkładać zmiennych. Raczej
pwsk[i] = &s[i];
w linii 7 oraz
printf("%c", *pwsk[i])
w linii 13.
W podejściu wskaźnikami właśnie te instrukcje prowadzą do błędów, groźnych błędów, wskaźniki tak zainicjowane jak w 6, 7 wskazują newralgiczne miejsca pamięci, zmiana może spowodować zwis systemu. Dlatego jest zakaz zmian w linii 3. I po co ta dodatkowa stała pp?
Otóż stała pp omija zabezpieczenia kompilatora, dzięki którym ten kod jest przyjęty bez kłopotów. Zwróćmy także uwagę na kasowanie napisu w 8.

Jest tylko jedno rzutowanie w 12. Kompilator nie chce mieć zakresu zmiennej ograniczonej wskaźnikiem. Jest przesunięcie, gdyż pierwszy wskaźnik trzyma długość, jak AnsiString w Pascalu.
I chętni mogą skompilować oraz zobaczyć, że tablica wskaźników pwsk przechwyciła długość napisu i sam napis, by móc go wypisać na monitorze. Będą śmieci? Otóż nie...


Kto nie wierzy, niech sprawdzi... Sprawdzone w GCC pod DOSem.

Brak komentarzy: