Witam!
Mam kilka pytań odnośnie zarezerwowanej pamięci przeznaczonej do dalszego użytku (np. korzystają z niej operatory new i delete).
Pytanie 1.
Na początek pytanie czy dobrze to rozumiem: jeżeli mamy zwykłą pamięć, np. 2 GB. To jeżeli programy uruchomione w systemie używają ok. 500 MB, to na program zostanie przeznaczona prawie cała wolna czyli ok. 1,5 GB (na program nasz + dla kompilatora itp.). To tak w uproszczeniu. I teraz ta rezerwacja pamięci odbywa się w ramach tej całej wolnej ? Jak to z tym dokładnie bywa ?
Pytanie 2.
Możemy przepełnić tą pamięć zarezerwowaną. Są trzy sposoby, żeby nad tym zapanować:
* zwrócenie adresu zero do wskaźnika ( std::nothrow )
* rzucenie wyjątku std::bad_alloc
* przygotowanie specjalnej funkcji na awarię - set_new_handler
Pytanie 2 brzmi: jak nic nie określimy to co się stanie w najczęściej - tzn. jak zareaguje kompilator ? Żeby wszystko było jasne to nie mogę sprawdzić wszystkich tych pytań sam, bo pracuję na VM, a ona ma jakby inne komunikaty o braku pamięci niż normalny Windows…
Przykładowo mamy taki kod:
#include
using namespace std;
int main()
{
try
{
double *wsk;
for( ; ; ) //w końcu nastąpi przepełnienie...
{
wsk = new double;
}
}
catch(bad_alloc) // <---tak naprawdę to nazywa się ona: std::bad_alloc
{
cout << "Przechwycona nieudana rezerwacja pamieci !";
}
cout << "\n\n\n\n\n\n---------------------------------------------------------------\n";
system("pause");
}[/code]
Wiem co on oznacza - po przepełnieniu wykona się blok [b]catch[/b].
A teraz 3 opcja zareagowania na brak pamięci:
[code]#include #include #include using namespace std; //----------------------- void funkcja_alarmowa(); //nasza funkcja do obsługi wyjątków long k; //globalna zmienna ‘k’ int main() { set_new_handler(funkcja_alarmowa); for(k = 0 ; ; k++) { new int; //rezerwacja miejsca na obiekt } cout << “\n\n\n\n\n\n---------------------------------------------------------------\n”; system(“pause”); } //***************************************** void funkcja_alarmowa() { cout << “\nZabraklo pamieci przy k = " << k << " !”; exit(1); }
Biblioteka new :
#include
Odpowiada za deklarację set_new_handler. Natomiast:
#include
żeby można było użyć:exit(1);****Pytanie 3. Co oznacza to exit(1);:?: Nie jest to wytłumaczone wcale… Tutaj: http://publib.boulder.ibm.com/infocente … newhnd.htmJest napisane, że może być zamiast tego**abort(); też. Ale co oznaczają te instrukcje i liczba w nawiasie ? Pytanie 4.**W książce jest napisane:
I wcześniej był taki komentarz w programie pod exit():
exit(1);
// throw bad_alloc();
Tu chodziło autorowi o coś takiego :?:
#include
#include
#include
using namespace std;
//-----------------------
void funkcja_alarmowa(); //nasza funkcja do obsługi wyjątków
long k; //globalna zmienna 'k'
int main()
{
set_new_handler(funkcja_alarmowa);
try //do wyjątku bad_alloc
{
for(k = 0 ; ; k++)
{
new int; //rezerwacja miejsca na obiekt
}
}
catch(bad_alloc) //"Łapiemy wyjątek"
{
cout << "\"Lapiemy wyjatek\"";
}
cout << "\n\n\n\n\n\n---------------------------------------------------------------\n";
system("pause");
}
// *****************************************
void funkcja_alarmowa()
{
cout << "\nZabraklo pamieci przy k = "
<< k << " !";
exit(1);
}
O ile ten kod zadziała to co się pierwsze wykona - funkcja specjalna - tzn. ustalona przez set_new_handler czy blok catch(bad_alloc) :?:
Pytanie 5.
Pierwsza opcja, czyli zwracanie NULLa do wskaźnika to stary sposób. Dwa nowe to właśnie te ostatnie sposoby. Czym one się różnią tak naprawdę ? Przecież tu i tu “akcja alarmowa” jest przekazywana do bloku, do którego chcieliśmy ją przekazać. Raz jest przekazywana do bloku catch a drugi raz do bloku ustalonej przez nas funkcji.