Skip to content

H) Basic memory example

kalinosia edited this page Mar 13, 2021 · 1 revision

Odnoszenie do usuniętej pamięci

#include <iostream>
struct Msg{
    int value{333};
};
void seeMsg(Msg* msg){
std::cout<<msg->value<<std::endl;
}
int main(){
Msg * m = new Msg();
//code
seeMsg(m);
delete m;
seeMsg(m);

return 0;
}
OUTPUT
333
0 (lub śmieci lub dobra odpowiedź - przypadek)

Odnoszenie do usuniętej pamięci (delete) + przypisanie nullptr do wskaźnika

int *p=new int(10);
cout<<*p<<endl;
delete p;
cout<<*p<<endl;
p=nullptr;
cout<<*p<<endl;
OUTPUT
10
0 (tu niekoniecznie pokaże 0, może jakimś cudem pokazać dobrą wartość lub śmieci)
Segmentation fault (core dumped)

Usunięcie pamięci (delete) + nullprt i sprawdzenie

#include <iostream>
struct Msg{
    int value{333};
};
void seeMsg(Msg* msg){
std::cout<<msg->value<<std::endl;
}
int main(){
Msg * m = new Msg();
//code
seeMsg(m);
delete m;
seeMsg(m); //Here is ok but trash
if (!m) std::cout<<"not exist before nullptr\n"; //This not do because m =/= 0!
m=nullptr;
if (!m) std::cout<<"After delete m; and m=nullptr; - m not exist";
seeMsg(m); //Here is not ok and: Segmentation fault (core dumped)!!!
return 0;
}

Podwójne usunięcie pamięci

#include <iostream>
struct Msg{
    int value{333};
};
void deleteMsg(Msg* msg){
delete m;
}
int main(){
Msg * m = new Msg();
//code
deleteMsg(m);
delete m;

return 0;
}
OUTPUT
*** Error in './a.out':double free or corruption (fasttop): 0x00000000019coś ***
Aborted(core dumped)

Zwalnianie pamięci niedynamicznie alokowanej

class Msg{};
void processMsg(Msg* msg){
//do domething
//cout<<msg<<endl; //Da nam tu adres 
delete msg;
}
int main(){
Msg m; //PAMIĘĆ STATYCZNIE ALOKOWANA
//cout<<m<<endl; // NIE!!! error because not have anything
processMsg(&m);//przez referencję nie wskaźnik
}
OUTPUT
*** Error in `./a.out': free(): invalid pointer: 0x00007ffe906d470f *** 
Aborted 

Zwalnianie części pamięci dynamicznie alokowanej

#include <iostream>
#include <iterator>

int main()
{
constexpr auto size = 4u;//zdefiniowany rozbiar tab-4 unsize
int* array = new int [size]{1,5,3,4,2};
std::copy(array, array + size,
std::ostream_iterator<int>(std::cout, " _ "));

delete array; //!!!!! should be delete [] array;
}

Memory leak - nadpisanie

int main()
{
int* p = new int(10);
p = new int(20);
cout<<*p<<endl; //20, a adres komórki z 10 uciekł
delete p;
}

Dynamic array allocation

#include <iostream>

int main()
{
    int staticArray[] = {0,1,2,3,4,5,6,7,8,9};
    for (int i=0; i<10; i++){
        std::cout<<"staticArray["<<i<<"]: "<<std::flush;
        std::cout<<staticArray[i]<<std::endl;
    }
    
    int* dynamicArray = new int[10]; (wyrażenie new nie operator)
    for (int i=0; i<10; ++i){
        *(dynamicArray+i) = i*10;
    }
    for (int i=0; i<10; ++i){
        std::cout<<"dynamicArray["<<i<<"]: "<<std::flush;
        std::cout<<dynamicArray[i]<<std::endl; //cukier składniowy-ładniejszy zapis niż u góry
    }

    std::cout<<"Piąty(bo pierwsze 0) element tablicy: "<<*(dynamicArray+4);

    delete [] dynamicArray; //jeszcze przed pierwszym adresem jest rozmiar tablicy alokowany...size_t lub inaczej
}

Kopiowanie bloków pamięci

Przykład klasyczny:

for( int i = 0; i < ilosc; i++ ) nowybufor[ i ] = starybufor[ i ];

Przykład wydajniejszy:

void * memcpy( void * adres_docelowy, const void * adres_zrodlowy, size_t ilosc );

Jako pierwszy parametr (adres_docelowy) podajemy adres do pamięci pod którym mają się znaleźć nowe dane. Drugi parametr (adres_zrodlowy) to miejsce z którego dane mają zostać pobrane i również określamy je za pomocą adresu. Trzecim, a zarazem ostatnim parametrem (ilosc) jest ilość bajtów, jaka ma zostać przekopiowana ze źródła do celu. Kopiując małe bloki pamięci różnicy w szybkości działania programu nie zaobserwujesz, jednak gdy przyjdzie Ci kopiować kilka MB danych różnice czasowe mogą być już bardzo odczuwalne.

Clone this wiki locally