list::clear() и list::assign() почему-то портят vector, TaL, 17-Апр-07, 00:22 [смотреть все]Возможно я что-то глупое спрошу, но я уже второй день бьюсь и в инете нигде по сути ответа не могу найти, а сроки поджимают. Ситуация такая: есть код, в котором я создаю массив контейнеров std::list и контейнер std::vector:struct Addresses { unsigned short doc; unsigned short line; short word; //unsigned int key; void operator=(Addresses a); Addresses(); int Read(int &fileid, const int offset); }; struct united_list { Addresses addr; int* keys; united_list() { keys=NULL; }; ~united_list() { if(keys) delete[] keys; keys=NULL; }; }; typedef list<united_list> addList; struct TMatch { int addr_size; Addresses* addr; int key_size; int* keys; TMatch(); TMatch(int ad_size, int ky_size); ~TMatch(); void operator=(TMatch a); void Init(int ad_size, int ky_size); void clear(); }; addList* bigquery; vector<TMatch*> result; Затем происходят вызовы функций таким вот образом: int Intersect(const int offNum,Dist* &dist,addList* &adds,vector<TMatch*>& result); в ней вызывается функция void IntersectPair(const int i,Dist* &dist,addList* &adds); в обеих, обратите внимание, третий параметр - ссылка на созданый выше bigquery, result - он везде тот же result. Однако IntersectPair объекта result вообще не касается, при этом когда я после операций в IntersectPair пытаюсь сделать result.reserve(xxx); он пишет про ошибку glibc про corrupt list. Закоментировав вызов IntersectPair, ошибка исчезает, однако, естественно код работает неправильно. Возможно следующее подскажет, в чем может быть проблема. В том же месте кода я сделал такую вот трассировку: for(i=0;i<__size;i++) { resultSet=new TMatch(offNum,__sorter.key_sort_num); resultSet->addr[offNum-1]=adds_i_current_iterator->addr; result.push_back(resultSet); if(!i) { cout<<resultSet->addr[0].doc<<"."<<resultSet->addr[0].line<<"."<<resultSet->addr[0].word<<endl; cout<<adds_i_current_iterator->addr.doc<<"."<<adds_i_current_iterator->addr.line<<"."<<adds_i_current_iterator->addr.word<<endl; cout<<result[0][0].addr[0].doc<<"."<<result[0][0].addr[0].line<<"."<<result[0][0].addr[0].word<<endl; } adds_i_current_iterator++; } cout<<result[0][0].addr[0].doc<<"."<<result[0][0].addr[0].line<<"."<<result[0][0].addr[0].word<<endl; adds[offNum-1].clear(); cout<<result[0][0].addr[0].doc<<"."<<result[0][0].addr[0].line<<"."<<result[0][0].addr[0].word<<endl; а выдал он мне такую вот фишку: 1.2.2 1.2.2 1.2.2 1.2.2 6587.230.0 Опять же, за коментировав adds[offNum-1].clear() вывод становится нормальным 1.2.2 1.2.2 1.2.2 1.2.2 1.2.2 Кстати, в обоих случаях последующие элементы вектора results не страдают и нормально обрабатываются. ну то есть получается, что после вызова adds[offNum-1].clear(); у меня портится содержимое вектора result, хотя везде происходит присваивание по значениям, то есть создается где нужно новый обхъект, аллоцируется оператором new память и туда в нужные места заливаются значения соответственные. Помогите, пожалуйста, я ума не приложу, как у меня могут так хитро переплестись контейнеры. Скажите, если нужно дополнительно код выложить. Заранее спасибо. |
- list::clear() и list::assign() почему-то портят vector, dronord, 09:35 , 17-Апр-07 (1)
Странно вот это adds[offNum-1].clear(); Проследите за offNum, он правда везде >0 ?
- list::clear() и list::assign() почему-то портят vector, TaL, 11:35 , 17-Апр-07 (2)
>Странно вот это adds[offNum-1].clear(); >Проследите за offNum, он правда везде >0 ?Абсолютно точно offNum>=1.
- list::clear() и list::assign() почему-то портят vector, dronord, 11:59 , 17-Апр-07 (3)
Сделайте у united_list копирующий конструктор, потому что у Вас typedef list<united_list> addList; и в нем есть указатель int*.Ещё бы я сделал аргумент оператора присвоения у первой структуры передаваемым по ссылке или указателю.
- list::clear() и list::assign() почему-то портят vector, TaL, 12:41 , 17-Апр-07 (4)
>Сделайте у united_list копирующий конструктор, потому что у Вас typedef list<united_list> addList; и в нем есть указатель int*. > >Ещё бы я сделал аргумент оператора присвоения у первой структуры передаваемым по >ссылке или указателю. Не совсем понял,копирующий конструктор Addresses(Addresses&)? Относительно оператора присвоения, он у меня сейчас такой: void Addresses::operator=(Addresses& a) { doc=a.doc; line=a.line; word=a.word; } Этого недостаточно?
- list::clear() и list::assign() почему-то портят vector, TaL, 12:45 , 17-Апр-07 (5)
и еще, когда создается new TMatch(xxx) выполняется такой вот код TMatch::TMatch(int ad_size, int ky_size) { Init(ad_size,ky_size); } void TMatch::Init(int ad_size, int ky_size) { addr_size=ad_size; addr=new Addresses[addr_size]; key_size=ky_size; keys=new int[key_size]; } Я правильно понимаю, что этого недостаточно и лучше вместо присваивания использовать копирующий конструктор?
- list::clear() и list::assign() почему-то портят vector, TaL, 12:49 , 17-Апр-07 (6)
Я идею не совсем понял идею копирующего конструктора для united_list, потому как bigquery нормально инициализируется и не портится в процессе выполнения, проблема в том, что изменения в bigquery уже после копирования информации в вектор result портят этот вектор...
- list::clear() и list::assign() почему-то портят vector, dronord, 13:10 , 17-Апр-07 (7)
В list'е хранятся копии объектов, которые Вы туда положили. Если не реализовать правильный копир. конструктор и возможно оператор присвоения для united_list, компилятор сам их сгенерит и сделает это неверно, потому что в классе имеется указатель int* united_list::keys.Изменения Вашего обекта или объекта из list'а скажутся на объекте из list'а или Вашем, соответственно. Последствия предсказать не могу.
- list::clear() и list::assign() почему-то портят vector, TaL, 15:26 , 17-Апр-07 (8)
>В list'е хранятся копии объектов, которые Вы туда положили. >Если не реализовать правильный копир. конструктор и возможно оператор присвоения для united_list, >компилятор сам их сгенерит и сделает это неверно, потому что в >классе имеется указатель int* united_list::keys. > >Изменения Вашего обекта или объекта из list'а скажутся на объекте из list'а >или Вашем, соответственно. Последствия предсказать не могу. Проверил аккуратно код, связанный с int* united_list::keys - коряво написано, но по существу все аллоцирование и присваивание производится мною явно.
- list::clear() и list::assign() почему-то портят vector, TaL, 15:30 , 17-Апр-07 (9)
Я наверно, не на том заострил внимание в исходном посте. Суть проблемы вот какая:main() { ... vector<TMatch*> result; int NumberOfResults=Intersect(Params.NumOfOffsets,Params.SearchDistances,bigquery,result); ... } где int Intersect(const int offNum,Dist* &dist,addList* &adds,vector<TMatch*>& result) { ..../*тут ничего не трогает result*/ IntersectPair(i,dist,adds); Sweep(offNum,dist,adds,result); ..../*тут ничего не трогает result*/ } где void IntersectPair(const int i,Dist* &dist,addList* &adds) { (к result вообще доступа не должно быть) } void Sweep(const int offNum,Dist* &dist,addList* &adds,vector<TMatch*>& result) { int __size=adds[offNum-1].size(); cout<<__size<<" "<<result.capacity()<<endl; result.reserve(__size); cout<<__size<<" "<<result.capacity()<<endl; ... } то есть до места result.reserve(__size); !единственное! обращение к объекту result это его создание с помощью vector<TMatch*> result; Но вот что пишет мне указанное место из кода Sweep: 18537 0 *** glibc detected *** corrupted double-linked list: 0x00002b8fc5f0e158 *** Но ведь result - это vector. А если поврежден list adds (он же bigquery), то почему ошибка выводится при обращению к члену-функции vector::reserve(int)?
- list::clear() и list::assign() почему-то портят vector, dronord, 15:59 , 17-Апр-07 (11)
Покажите backtrace. Вообще, лист должен разваливаться. Почему? Я изложил и ещё раз повторюсь =). Указатель keys копии объекта в листе указывает туда же, куда и указатель исходного объекта. Следовательно, изменение одного из них затронет общую память - произойдет падение или все что угодно. В структуре united_list необходимы копир. конструктор и оператор присвоения, которые правильно обработают указатель.
- list::clear() и list::assign() почему-то портят vector, Arifolth, 16:00 , 17-Апр-07 (12)
>Покажите backtrace. >Вообще, лист должен разваливаться. Почему? Я изложил и ещё раз повторюсь =). >Указатель keys копии объекта в листе указывает туда же, куда и >указатель исходного объекта. Следовательно, изменение одного из них затронет общую память >- произойдет падение или все что угодно. В структуре united_list необходимы >копир. конструктор и оператор присвоения, которые правильно обработают указатель. а чего valgrind хорошего говорит про ваше приложение?
- list::clear() и list::assign() почему-то портят vector, TaL, 17:35 , 17-Апр-07 (16)
>>Покажите backtrace. >>Вообще, лист должен разваливаться. Почему? Я изложил и ещё раз повторюсь =). >>Указатель keys копии объекта в листе указывает туда же, куда и >>указатель исходного объекта. Следовательно, изменение одного из них затронет общую память >>- произойдет падение или все что угодно. В структуре united_list необходимы >>копир. конструктор и оператор присвоения, которые правильно обработают указатель. > > >а чего valgrind хорошего говорит про ваше приложение? а valgrind молчит, равно как и gdb, потому как их нету (вот такой вот сюрприз, мне тоже было приятно), а локально тестить систему невозможно...
- list::clear() и list::assign() почему-то портят vector, TaL, 16:31 , 17-Апр-07 (13)
>Покажите backtrace. >Вообще, лист должен разваливаться. Почему? Я изложил и ещё раз повторюсь =). >Указатель keys копии объекта в листе указывает туда же, куда и >указатель исходного объекта. Следовательно, изменение одного из них затронет общую память >- произойдет падение или все что угодно. В структуре united_list необходимы >копир. конструктор и оператор присвоения, которые правильно обработают указатель. Пункт 0. Я может быть туплю совсем, вы не могли бы в код united_list добавить то, что вы конкретно имеете в виду... копирующий что именно конструктор? Пункт 1. Бог с ним с листом - он нормально работает :) В копии листовой указаетль keys указывает на другое место, которое создается при заполнении temp.keys=new int[num_keys]; for(l=0;l<num_keys;l++) { temp.keys[l]=ReadKey(Params.Offsets[i][j]+k,__sorter.sorters[key_ind[l]].keysort); } _iterator=adds[i].insert(_iterator,temp); Я этот контейнер просто руками заполняю каждый отдельный. Вы это имели в виду? Кроме того, на тех примерах, на которых я щас тестил я специально задавал условия, чтобы keys==NULL все время (а то и там бы наверно намучался бы). Несчастье мое не в том что лист вредится или не туда указывает, а в том, что когда я его освобождать начинаю, портится vector, который я создаю независимо от этого листа...
- list::clear() и list::assign() почему-то портят vector, dronord, 16:52 , 17-Апр-07 (14)
Синхронизируйте этот код со своим и ждем отчет =) П.С. Код не компилировал, надеюсь смысел понятен.
class united_list { ...public: int keys_size; int *keys; // Для примера сделал открытым членом /* * Копирующий конструктор */ united_list ( const united_list & obj ) { this->addr = obj.addr; this->keys = new int[ obj.keys_size ]; for ( int i = 0; i < obj.keys_size; ++i) { this->keys[i] = obj.keys[i]; } } /* * Оператор присвоения */ united_list &operator=(const united_list &obj ) { this->addr = obj.addr; delete [] this->keys; // Прежние значения боле не нужны this->keys = new int[ obj.keys_size ]; for ( int i = 0; i < obj.keys_size; ++i) { this->keys[i] = obj.keys[i]; } return *this; } };
- list::clear() и list::assign() почему-то портят vector, TaL, 17:33 , 17-Апр-07 (15)
Мусчина, вы волшебник!! Я не понял, на какое именно место повлияло, результат сирано неправильный - видимо дальше уже алгоритмическая обшибка, но теперь хотя бы не вылетает...Поделитесь секретом, какое место я не дочитал? Ну то есть, что я сделал только что?%)
- list::clear() и list::assign() почему-то портят vector, dronord, 18:18 , 17-Апр-07 (17)
Это из собственного опыта. Потом уж не помню, нашел у Страуструпа или нет. Какой метод из двух нужен, зависит, наверное, от компилятора. У меня (gcc 3.4.6) было достаточно копирующего конструктора.
|