Сбой вектора возврата C++ после возврата объекта и выхода из функции

Проблема заключалась в глупой ошибке другого класса при доступе к вектору и удалении итераторов. Ничего общего с кодом ниже. Извините за потраченное время.

Я должен упустить что-то элементарное. У меня есть функция, которая создает объект, манипулирует его данными, а затем помещает их в вектор. В момент выхода из функции программа вылетает с SIGSEV, и я смотрю на (Kdevelop gcc 4.5 gdb):

   /**
   *  The dtor only erases the elements, and note that if the
   *  elements themselves are pointers, the pointed-to memory is
   *  not touched in any way.  Managing the pointer is the user's
   *  responsibility.
   */
  ~vector()
  { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
          _M_get_Tp_allocator()); }

Я не храню указатели, я пытаюсь хранить созданные объекты.

void Init::initIndividual(int ID, int gen)
{
  Individual temp_person = Individual(ID,gen);
  int inst_size = getRandom<int>(1,max_inst_size);
  for (int k=0;k<inst_size;k++)
  {
    retry:
    // (1) randomly choose a body part
    int body_num = getRandom<int>(1,20);
    body_part temp_part = get_body_part(body_num);
    // NOTE: We need to make sure that the body part is unique!
    std::vector<Instruction> already_existing = temp_person.get_instructions();
    if (already_existing.size() > 0)
    {
      for (int a=0; a< already_existing.size();a++)
      {
       std::string name = already_existing[a].get_body_part();
       if ( name.compare(temp_part.name) == 0 )
       { //if body part already exists in the list, retry!
         goto retry;
       }
      }
    }    
    // (2) Create a new Instruction for this body part
    Instruction temp_inst = Instruction(temp_part.name,temp_part.max_angle,temp_part.min_angle);
    // (3) Randomly pick a number of body parameters to use
    int paramsize = getRandom<int>(1,max_params_size);
    // (4) Randomly choose time and degree trajectory parameters for this body part and append!
    for (int x=0;x < paramsize; x++)
    {
     float time = 0.0f;
     int choice = 0;
     // (4.a) If begin of body parameters
     if (x==0)
     {
   //if always start at time = 0
   if (static_time_init)
   {
     time = 0.0f;
   }
   //if randomly choose the init time
   else if (!static_time_init)
   {
     time = getRandom<float>(0.0f,(float)(time_constrain-1));
   }
     }
     // (4.b) if not @ start of params
     else if(x!=0)
     {
       redo:  
       float previous_time = temp_inst.parameters.back().time; //get previous time
       double incrementor = getRandom<double>(0.1,1.0); //increment time by min 0.1 max 1.0
       time = previous_time + (float)incrementor;
       if (time > time_constrain) //if current time is more than time constrain, redo
       { 
        goto redo;
       }
     }
     // (5) Randomly pick a degree to move to (within body part constrains)
     float degree = getRandom<float>(temp_inst.get_min_angle(),temp_inst.get_max_angle());
     Parameter foo = Parameter(time,degree);
     temp_inst.add_parameter(Parameter(time,degree));
   }
  temp_person.add_Instruction(temp_inst);
  }
  temp_person.endtime = time_constrain;
 }

Вот и вся функция.

 std::vector<Individual> population;

Разве функция push_back не копирует объект при возврате? Вызывается ли деструктор, потому что push_back пытается уничтожить temp_person ? Я не определил оператор копирования в классе Individual. Я сталкивался с этой проблемой раньше и никогда не понимал ее. Это происходит из-за того, что в конце функция temp_person выходит за рамки? Благодарю вас !

Редактировать: Индивидуальный класс

class Individual 
{
   friend class Population;
   friend class Crossover;
   friend class Init;
 private:
   std::string xml_file;
   char *arg4;
 protected:
   bool saved, mutated, dead;
   unsigned int UID, generation;
   int executions;
   std::vector<Instruction> instructions;
   int father_UID, mother_UID;
   double eta,endtime;
 public:
   int uniform;
   float fitness;
   pthread_mutex_t thread_mutex;
   //Some other functions irrelevant

Обратите внимание, что вектор инструкций имеет еще один вектор структур.

class Instruction 
{
  friend class Crossover;
 private:  
  unsigned int param_size;
  float max_angle, min_angle;
  bool micro_mutated;
 public:
  std::string body_part;
  std::vector<Parameter> parameters;
  //other stuff

class Parameter
{
  public:
   float time;
   float degree;
   Parameter(float t,float d);
};

Здесь нет ничего сумасшедшего.

Может ли это быть проблемой неглубокой копии, полученной с помощью pool.push_back?


person Ælex    schedule 24.06.2011    source источник
comment
Соответствует ли класс Individual правилу трех? Есть ли в нем необработанные указатели, указывающие на память кучи или другие дескрипторы ресурсов, которые освобождаются в деструкторе?   -  person fredoverflow    schedule 24.06.2011
comment
Можете ли вы опубликовать определение Individual? В частности, содержит ли Individual вектор в какой-либо форме?   -  person dolphy    schedule 24.06.2011
comment
Да Индивидуальный содержит векторы других классов. Может быть это оно? Размещу под вопросом.   -  person Ælex    schedule 24.06.2011
comment
Вероятно, нам также понадобится как минимум конструктор/деструктор. Мое предположение состоит в том, что у вас проблема не с population, а с уничтожением temp_person, поскольку оно выходит из области действия. Что-то в вашем поколении Individual небезопасно в отношении очистки.   -  person dolphy    schedule 24.06.2011
comment
Я не объявлял деструктор, только два конструктора для отдельных   -  person Ælex    schedule 24.06.2011
comment
У вас есть мьютекс в вашем классе Individual. Конструктор класса создает его, а деструктор класса удаляет? Как вы справляетесь с копированием мьютексов?   -  person Nicol Bolas    schedule 24.06.2011
comment
Опубликуйте их, и то же самое вполне может относиться к Instruction и Parameter (и, возможно, даже глубже), в зависимости от того, что мы найдем в вашем конструкторе Individual. Суть такова: точно отследите, что происходит при создании Individual, а затем начните работать в обратном направлении, чтобы точно увидеть, что происходит при уничтожении всего.   -  person dolphy    schedule 24.06.2011
comment
Сверчки, которые вы слышите, являются результатом того, что все читают и перечитывают, чтобы убедиться, что они видят слово goto.   -  person dolphy    schedule 24.06.2011
comment
Мьютексы инициализируются из конструктора (и, к сожалению, никогда не удаляются, потому что я еще не реализовал деструктор). Кстати, что такого злого в goto?   -  person Ælex    schedule 24.06.2011
comment
Я думаю, что goto может иметь свое применение, но оно должно быть чрезвычайно оправдано... (больше, чем просто удобство или поверхностная производительность). Все эти причины вероятно включают в себя слова «политический» или «наследие». Вот обсуждение!. В любом случае, я рад, что вы нашли проблему.   -  person dolphy    schedule 24.06.2011


Ответы (3)


pthread_mutex_t thread_mutex;

Копирование pthread_mutex_t не имеет смысла. Держу пари, это часть проблемы. У меня тоже есть подозрения насчет твоего char*; кому он принадлежит?


Мое обоснование того, почему я считаю, что pthread_mutex_t нельзя скопировать: единственный задокументированный способ получить инициализированный мьютекс - это использовать pthread_mutex_init. Кроме того, все функции pthread_mutex_* управляют мьютексами, используя передачу по указателю (в отличие, например, от pthread_thread_t).

person Luc Danton    schedule 24.06.2011
comment
Я не знал, что их копирование незаконно, но на данный момент потоки не используются. - person Ælex; 24.06.2011
comment
pthread_mutex инициализируется в конструкторе. Я могу переместить это в другое место, так как позже я использую потоки для одновременного выполнения многих людей. Тем не менее, мне нужен pthread_mutex, принадлежащий индивидууму. char * не инициализирован, он используется как временный параметр, я мог бы обойтись без него. - person Ælex; 24.06.2011

Doesn't the push_back function copy the object when pushing it back ? 

Да, это так.

Is the destructor invoked because push_back is trying to destroy temp_person?

Нет. Он вызывается, потому что временный объект уничтожается в конце функции.

I have not defined a copy operator in class Individual. 

Давайте посмотрим объявление класса.

Does this happen because at the end of the function temp_person is out of scope ?

Да, временный объект уничтожается, но если с классом все в порядке, это не должно быть проблемой. Опять же - нам нужно видеть код.

Бьюсь об заклад, это что-то с конструктором/деструктором (:

Кстати, population глобальный? Уч!

person Kiril Kirov    schedule 24.06.2011
comment
Нет, весь код является частью другого класса, частные переменные которого содержат население. Я опубликовал остальные классы, думаю, мне также следует опубликовать всю функцию, которая вызывает проблему? - person Ælex; 24.06.2011
comment
@Alex - да, пожалуйста, вставьте всю проблемную функцию и сообщите нам, является ли она общедоступной или ее можно вызвать из общедоступной. Я вижу здесь мьютексы, так что это многопоточное приложение. Вы уверены, что все потокобезопасно? Кроме того, для чего char *arg4? Как вы с этим справляетесь? Используете ли вы new[]/delete[] для выделения памяти для него? Если это так, то у вас должен быть какой-то конструктор копирования для правильной обработки при копировании объекта (вталкивание его обратно в vector) - person Kiril Kirov; 24.06.2011
comment
На данный момент потоки не используются, вся инициализация использует случайные значения. Я не использовал new или delete нигде в этом проекте. char *arg4 временно используется для передачи некоторых значений сериализатору. Выложу всю функцию как есть. - person Ælex; 24.06.2011
comment
Может ли это быть проблемой поверхностного копирования? - person Ælex; 24.06.2011
comment
В начале я думал об этом, но как вы говорите, что char* arg4 используется правильно :? Вы пытались удалить мьютекс, как сказал @Luc Danton? Не думаю, что это опасно, но точно не знаю. - person Kiril Kirov; 24.06.2011
comment
Теперь я получаю std::bad_alloc ! lol Нет, это не мьютекс, я пробовал с ним и без него. Вероятно, что-то в коде, который обращается к векторам - person Ælex; 24.06.2011
comment
std::bad_alloc - лол, это действительно шокирует :D Хммм, что это за класс Parameter ? Посмотрим его декларацию. Кроме того, конструктор Individual, Instruction и Parameter. Лол, думаю, это много кода :D Теперь у меня есть другая теория - что-то не так с Parameter (подсказка - std::vector<Parameter> parameters в Instructions) - person Kiril Kirov; 24.06.2011
comment
Я думаю, что проблема в населении. Он пытается скопировать вектор из класса инициализации, но почему-то не получается. Индивиды теперь инициализируются без сбоев, все, что я сделал, это закомментировал инициализацию pthread_mutex в конструкторе. - person Ælex; 24.06.2011
comment
Я исправил это, пожалуйста, не ненавидьте меня, это была глупая ошибка в Населении. Ничего общего с векторами. Очень жаль потраченного времени. Кстати, что было бы более эффективным способом выполнить эту функцию инициализации без создания объекта и последующего его копирования? - person Ælex; 24.06.2011
comment
@Alex - ха-ха, успокойся, никто тебя не возненавидит :D В чем была ошибка, мне любопытно? Насчет функции init - ну не могу сказать, не зная всей логики и не видя всей картины, чего не могу, так как слишком много кода. Но я бы посоветовал переделать код или хотя бы эту функцию. Выглядит слишком сложно, а раз один код усложнился - значит с логикой что-то не так :p И, кстати, меня эти goto-ы немного пугают :D - person Kiril Kirov; 24.06.2011
comment
Был запущен еще один поток, который удалял мертвых людей, изменял размер вектора и делал недействительными некоторые итераторы. Как только я отключил его, он работал нормально. Goto в этом случае - необходимое зло, я мог бы сделать это с помощью циклов, но это означало бы еще больше кода. Большое спасибо за помощь и за ответы на мои вопросы! - person Ælex; 24.06.2011
comment
Добро пожаловать (: Итак, это оказалось проблемой многопоточности, мое первое подозрение: P Удачи с приложением (= - person Kiril Kirov; 24.06.2011

Проблема заключалась в глупой ошибке другого класса, который получил доступ к вектору и удалил итераторы. Ничего общего с кодом выше. Извините, что потратил ваше время.

person Ælex    schedule 24.06.2011