Не може да се върне правилно към вектор, който е в структура C++

В момента имам структура p, която съдържа вектор на друга структура, наречена pg. Ето структурата на процеса:

struct p{
int i;
int s;
vector<pg*> pT;

void addP(struct pg* nP){
    pT.push_back(nP);
}

};

Някъде другаде в програмата създавам нова p структура, като правя:

struct p *p1= (struct p*) malloc(sizeof(struct p));

и след това присвоете стойности на id и size. Искам да добавя нова страница към pT вектора на структурата. Така че решавам, че мога да направя p1-> addP(makeP()), където makePreпревръща указател към pg структура, pg*.

Ето връзка към това, което gdb показва, когато направи segfaults. Също така се споменава, че това се случва на линията push_back. http://imgur.com/KZOGnI9

Нещо не е наред с указателите? Или не разпределям правилно паметта за вектора?


person user3261941    schedule 31.03.2016    source източник
comment
Този вектор от голи указатели винаги ще ви даде gyp.   -  person Bathsheba    schedule 31.03.2016
comment
malloc не извиква конструктора на process. Следователно вашият pageTable не е конструиран правилно, само паметта е запазена. Опитайте new!   -  person knivil    schedule 31.03.2016
comment
Не трябва да използвате malloc за създаване на нов process - конструкторът за pageTable няма да бъде извикан - използвайте new - все пак това е C++...   -  person Paul R    schedule 31.03.2016
comment
@Bathsheba Не толкова, колкото разпределянето на обект с вектор с помощта на malloc.   -  person juanchopanza    schedule 31.03.2016
comment
По-скоро използвайте new вместо malloc(), когато са включени C++ сложни класове като std::vector.   -  person πάντα ῥεῖ    schedule 31.03.2016
comment
@juanchopanza Да, наистина това ще ви създаде много проблеми!   -  person Bathsheba    schedule 31.03.2016
comment
Абсолютно сигурни ли сте, че трябва да разпределите proc динамично? Ако не знаете, тогава не го правете. Само process proc;.   -  person juanchopanza    schedule 31.03.2016


Отговори (2)


Използването на malloc в C++ почти винаги е лоша идея. Във вашия случай това води до това, че конструкторът за struct process не се извиква, което от своя страна означава, че конструкторът на неговия член pageTable също не се извиква.

Следователно вие извиквате push_back на неинициализиран вектор, което води до недефинирано поведение (и във вашия случай срив).

malloc вероятно работи само с "обикновени стари типове данни", т.е. типове, които не се нуждаят от конструкция (имат само конструктор по подразбиране и само обикновени стари типове данни като членове).

Правилният начин за разпределяне на обекти в купчината в C++ е използването на new, което изглежда като този:

process *p = new process; // possibly add constructor arguments here

Дори по-добър начин би бил да използвате интелигентни указатели, като std::unique_ptr или, ако са споделени изисква се собственост, std::shared_ptr.

Един още по-добър подход е изобщо да не използвате указатели, особено за обектите във вашия вектор, но вероятно също и за вашия struct process. Използвайте ги само ако се налага!

person Daniel Jour    schedule 31.03.2016
comment
А, добре. Само за да се уверя, че разбирам това правилно, добре ли е да използвам malloc за тази структура, ако, да кажем, векторът не е бил там и е имал само двете int променливи? И благодаря за помощта! - person user3261941; 31.03.2016
comment
@user3261941, просто се отървете от навика да използвате malloc() в C++ програми. Не е добре! - person SergeyA; 31.03.2016
comment
@user3261941 Вероятно, но (и това е голямо) просто недей. Няма абсолютно никаква причина да го правите и това ще доведе до проблеми по-рано, отколкото по-късно. - person Daniel Jour; 31.03.2016

Не е правилно да malloc вашият process обект, тъй като malloc няма да извика конструктора на структурата, която извиква конструктора на std::vector<page*>.

Ако е възможно, направете своя process обикновен автоматичен обект:

process proc;

Ако наистина имате нужда от динамично разпределение, използвайте new вместо malloc:

process* proc = new process;
person aschepler    schedule 31.03.2016