2016-02-09 4 views
0

У меня есть небольшая проблема с std::sort.std :: sort с ошибкой сегментации личного класса

Когда я пытаюсь сортировать выделенный массив объектов, используя переопределение функции «<» с std::sort, я получаю ошибку сегментации.

Вы можете увидеть проблему здесь ниже в примере игрушек: В моих class point, я выделяю массив личных вещей key (особенно выделяю память для массива v). Его элементы инициализируются, а затем я пытаюсь отсортировать этот массив.

С небольшими размерами (для массива v и массив для сортировки), я не получаю ошибки, а valgrind не возвращает никаких. Для больших размеров я получаю ошибку сегментации, а valgrind выводит много ошибок, которые я не понимаю.

Не могли бы вы мне помочь?

Спасибо!

using namespace std; 
#include <stdlib.h> 
#include <iostream> 
#include <algorithm> 
class key 
{ 
    public : 
     int size; 
     double *v, f; 

     key() {} 
     key(const key & k) 
     { 
      size = k.size; 
      f = k.f; 
      v = (double*)malloc(size*sizeof(double)); 
      for(int i=0;i<size;i++) 
       v[i]=k.v[i]; 
     } 
     ~key() 
     { 
      free(v); 
     } 
     bool operator<(const key& other) const 
     { 
      return f<other.f; 
     } 
     void init(int s) 
     { 
      size = s; 
      v = (double*)malloc(size*sizeof(double)); 
      for(int i=0;i<size;i++) 
       v[i]=((double)rand()/(RAND_MAX)); 
     } 
}; 
class point 
{ 
    public : 
     key *k; 

     point() {} 
     point(int param1, int param2) 
     { 
      k = (key*)malloc(param1*sizeof(key)); 
      for(int i=0;i<param1;i++) 
      { 
       k[i].init(param2); 
       k[i].f=param1-i; 
      } 
      std::sort(k,k+param1); 
      free(k); 
     } 
}; 


int main(int argc, char **argv) 
{ 
    point p(100,21200); // segmentation fault! 
    //point p(10,2); // no segmentation fault! 
    return 0; 
} 
+2

Почему вы используете 'malloc'? Почему бы не использовать 'std :: vector '? Только это одно изменение, вероятно, устранит проблему. Прямо сейчас, ваши классы не безопасно скопируются из-за отсутствия оператора копирования/присваивания для обработки этого 'double *' члена. Избавиться от него и заменить его на 'std :: vector' автоматически исправляет все эти проблемы. – PaulMcKenzie

+2

Это еще хуже. есть 'malloc' для массива' key ', который не является POD. Это не закончится хорошо. –

+0

Каковы ошибки, которые вы не понимаете в выводах valgrind? – immibis

ответ

3

Ваших классам нужен конструктор копирования (или конструктор перемещения) и оператор пользовательского назначения, потому что они управляют сырыми указатели (ресурсами). В противном случае, когда std::sort выполняет назначения объектов point или key, данные соответствующих объектов не копируются глубоко, но копируются только указатели. Затем ваш деструктор освобождает память для указателей, указывающих на один и тот же адрес памяти, что приводит к неопределенному поведению (вы часто получаете segfault для Linux/Unix). Также удалите эти malloc/free s и замените их на new[]/delete[]. Или лучше, используйте стандартные контейнеры, такие как std::vector.

Обратите внимание, что некоторые компиляторы могут уловить эти проблемы во время компиляции. Например, НКА с -Weffc++ выплевывает предупреждение:

предупреждения: struct Foo имеет элементы данных указателя [-WeffC++] , но не отменяет Foo(const Foo&)

+1

Класс нуждается в конструкторе копирования, потому что он управляет ресурсом, а не потому, что он содержит необработанные указатели. –

+0

@BenjaminLindley Да, конечно, формулировка была немного неряшливой, отредактированной. – vsoftco

+0

@vsoftco Я добавил конструктор копирования (см. Правки), но он не работает. – user85022

Смежные вопросы