The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
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;
          }

          };




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру