Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Problem z vector::emplace_back i znikająca pamięć?

Ostatnio zmodyfikowano 2020-01-05 18:37
Autor Wiadomość
Szustarol
Temat założony przez niniejszego użytkownika
Problem z vector::emplace_back i znikająca pamięć?
» 2020-01-04 23:06:48
Witam.
Napotykam problem podczas implementacji pewnego schematu:
C/C++
#include <iostream>
#include <vector>
#include <cstdlib>

class child {
public:
    char * data;
    unsigned size;
    child() {
        data =( char * ) malloc( sizeof( char ) * 8 );
        size = 8;
    }
    ~child() {
        free( data );
    }
    void resize( unsigned size ) {
        data =( char * ) realloc( data, size * sizeof( char ) );
        this->size = size;
    }
};

class parent {
public:
    child ch;
    void print() {
        for( unsigned i = 0; i < ch.size; i++ ) {
            std::cout << ch.data[ i ];
        }
        std::cout << std::endl;
    }
    parent( char dataval ) {
        ch.resize( 40 );
        for( unsigned i = 0; i < 40; i++ ) ch.data[ i ] = dataval;
       
        std::cout << "In constructor: " << std::endl;
        print();
    }
    ~parent() {
       
    };
};


int main() {
    std::vector < parent > par;
    for( char i = 'a'; i < 'z'; i++ ) {
        par.emplace_back( i );
        std::cout << "Outside constructor: " << std::endl;
        par.at( par.size() - 1 ).print();
    }
}

Schemat w pisanym przeze mnie programie jest podobny, ale bardziej skomplikowany, dlatego stworzyłem
wypisany powyżej program, który ma za zadanie zademonstrować mój problem, mianowicie w programie nagle dane utworzone
w konstruktorze są inne niż dane które są odczytane z klasy jakiś czas później. W przypadku mojego programu
dane nie są inne, bo przypuszczalnie program za mało robi w tzw. międzyczasie, ale
tak czy inaczej po utworzeniu kilkunastu instancji za pomocą emplace back program się wysypuje.
Gdy zastąpie
C/C++
par.emplace_back( i );
std::cout << "Outside constructor: " << std::endl;
par.at( par.size() - 1 ).print();
przez
C/C++
parent p;
std::cout << "Outside constructor: " << std::endl;
p.print();

wszystko działa jak należy i się nie wysypuje - więc problem ewidentnie wynika z użycia wektora. Co robię nie tak?
P-175959
nanoant20
» 2020-01-05 09:33:22
więc problem ewidentnie wynika z użycia wektora. Co robię nie tak?
z vector'em wszystko o.k.
zakomentuj w destruktorze
C/C++
~child() {
    //free( data );
}
P-175960
pekfos
» 2020-01-05 11:45:21
Brakuje poprawnej implementacji konstruktora kopiującego i operatora przypisania. Odpowiedź powyżej niczego nie naprawia i tylko wprowadza wyciek pamięci.
P-175961
Szustarol
Temat założony przez niniejszego użytkownika
» 2020-01-05 17:59:21
okej, dzięki @pekfos za wyjaśnienie - rozumiem że taki konstruktor jest potrzebny, ponieważ w pewnym momencie wektor
przy emplace back robi kopię obiektu parent, a więc i obiektu child w nim. Mam jednak dylemat - przecież
emplace_back z założenia jest funkcją która (chyba) nie powinna nic kopiować i powinna konstruować obiekt bezpośrednio w pamięci wektora-
teoretycznie żadne kopiowanie a tym bardziej przypisanie nie powinno być miejsca. Przykład ten dowodzi jednak, że jestem w błędzie - dlaczego tak się dzieje?
P-175971
pekfos
» 2020-01-05 18:05:48
emplace_back z założenia jest funkcją która (chyba) nie powinna nic kopiować i powinna konstruować obiekt bezpośrednio w pamięci wektora-
teoretycznie żadne kopiowanie a tym bardziej przypisanie nie powinno być miejsca.
Wektor trzyma elementy w ciągłym obszarze pamięci i jeśli bieżąca pojemność jest zbyt mała, wszystkie elementy są kopiowane / przenoszone w nowe miejsce. Musiałbyś zarezerwować odpowiednio dużo pamięci wywołaniem reserve() żeby tego uniknąć.
P-175972
Szustarol
Temat założony przez niniejszego użytkownika
» 2020-01-05 18:37:49
No tak, zapomniałem o tym fakcie - mojej uwadze umknęło to, że przecież kilka pierwszych elementów jest pomyślnie umieszczanych. Wszystko jasne, dzięki za pomoc
P-175974
« 1 »
  Strona 1 z 1