Ошибка сегментации при доступе к списку внутри структуры - PullRequest
2 голосов
/ 02 апреля 2011

Я постараюсь прояснить ситуацию.

Вот моя структура:

struct scopeList{
       int id;
       list<int> internal_list;
};
typedef struct scopeList scopeList_T;

Вот код, который дает мне сегментацию.

int main(){
    scopeList_T* t1 = (scopeList_T*) malloc(sizeof(scopeList_T));
    t1->id = 5; //works fine
    t1->internal_list.push_front(5); //segmentation fault
} 

Так как я выделяю память, и доступ к идентификатору в порядке, почему это вызывает ошибку сегментации? Должен ли я сначала сделать что-то особенное для списка?

Спасибо!

Ответы [ 5 ]

5 голосов
/ 02 апреля 2011

Используйте new вместо malloc!

sopeList_T* t1 = new scopeList_T;

malloc не запускает никаких конструкторов. Когда вам нужно освободить это struct, используйте delete вместо free - вы не можете free объекты, выделенные с помощью newfree не вызывает деструкторы).

Вам также не нужен этот typedef, достаточно объявления struct.

struct scopeList {
    int id;
    list<int> internal_list;
};

int main()
{
    scopeList *t = new scopeList;
    ....
    delete t;
    ....
}
1 голос
/ 02 апреля 2011

Правильные ответы были даны выше: вы выделили память вашей структуры, но не запустили никаких конструкторов для подобъектов, находящихся в неинициализированном состоянии.Я должен настаивать: это абсолютный запрет.НИКОГДА не путайте вызовы alloc & Co. с кодом C ++.

1 голос
/ 02 апреля 2011

Выделения памяти недостаточно.Вы также должны вызвать конструктор.

Наиболее распространенный и рекомендуемый способ простого динамического выделения в C ++ -

scopeList_T* t1 = new scopeList_T;

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

delete t1;

ADD:

Если вам действительно нужно использовать другой распределитель памяти (например, malloc/ free или что-то в вашем собственном дизайне), тогда вы должны выделить память и вызвать новое размещение (это похоже на явный вызов конструктора).Когда вы закончите с объектом, вы должны явно вызвать деструктор и затем освободить память.Важная вещь: память, выделенная для объекта, должна соответствовать требованиям выравнивания для этого типа объекта.

Пример:

// allocating memory
void* p = my_alloc( sizeof(scopeList_T) );

if( p == NULL )
{
// report allocation error and throw or return
}

// placement new operator
scopeList_T* t1 = new(p) scopeList_T; // t1 == p

// do some thing with the object
// .............................

// call destructor explicitly
t1->~scopeList_T();
// free memory
my_free(p); // or free(t1); that is the same
1 голос
/ 02 апреля 2011

Поскольку malloc не вызывает конструктор, вы можете сделать один из этих двух способов:

  1. Используйте new, чтобы выделить память, а также построить объект:

    sopeList_T* t1 = new scopeList_T;//it allocates and then call the ctor!
    
    //use delete to deallocate the memory
    delete t1;
    
  2. Или используйте malloc для выделения памяти, которую вы уже делаете, и используйте размещение new для создания объекта:

    scopeList_T* t1 = (scopeList_T*) malloc(sizeof(scopeList_T)); //allocation
    t1 = new (t1) scopeList_T; //it calls the ctor 
    
    //use free to deallocate the memory
    t1->~scopeList_T(); //call the destructor explicitly - necessary!
    free(t1);
    
1 голос
/ 02 апреля 2011

Вы не инициализируете список с помощью конструктора, таким образом, оставляя недопустимые данные в позиции internal_list.

...