Как выделить память для структуры с указателем на массив структур в C? - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть функция, которая создает и возвращает новый объект для списка, но у меня проблемы с распределением памяти (ошибка: ядро ​​сброшено). Я подумал, что это из-за '* модель', которая является указателем на массив для структур. Я совершенно новичок в динамическом распределении памяти и не уверен, что и как выделять нужный объем памяти.

Функция:

// Return a newly created object based on the arguments provided. 
object_t *create_object(SDL_Surface *surface, triangle_t *model, int numtriangles)
{
    // Allocate memory for a new object
    object_t *new_obj = malloc(sizeof(object_t));
        if (new_obj == NULL)
            return NULL;
    // Allocate memory for the model array
    triangle_t *arrayPtr = malloc((sizeof(triangle_t))*numtriangles);
        if (arrayPtr == NULL)
            return NULL;

    // Assign values
    arrayPtr = model;
    new_obj->model = arrayPtr;
    new_obj->numtriangles = numtriangles;
    new_obj->surface = surface;
    // Return created object
    return new_obj;
}

Вызов функции в основном:

object_t *ball = create_object(surface, sphere_model, SPHERE_NUMTRIANGLES);

Структура:

typedef struct object object_t;
struct object {
    float       scale;
    float       rotation;
    float       tx, ty;
    float       speedx, speedy;
    unsigned int ttl;          
    int         numtriangles;
    triangle_t  *model;
    SDL_Surface *surface;
};

typedef struct triangle triangle_t;
struct triangle {
    int x1, y1;
    int x2, y2;
    int x3, y3;
    unsigned int fillcolor;
    float scale;
    int tx, ty;
    float rotation;
    SDL_Rect rect;
    int sx1, sy1;
    int sx2, sy2;
    int sx3, sy3;
};

Массив:

#define SPHERE_NUMTRIANGLES    478   // <-- Array size
triangle_t sphere_model[] = {
{
.x1=-1,
.y1=-500,
.x2=-1,
.y2=-489,
.x3=-1,
.y3=-500,
.fillcolor=0xeeeeee,
.scale=1.0
},
{
.x1=-1,
.y1=-489,
.x2=-1,
.y2=-500,
.x3=40,
.y3=-489,
.fillcolor=0xbb0000,
.scale=1.0
},
...

Я пытался object_t *new_obj = malloc(sizeof(object_t) + (sizeof(triangle_t)*numtriangles));, но безуспешно.

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Итак, похоже, что object_t *new_obj = malloc(sizeof(object_t) + (sizeof(triangle_t)*numtriangles)); - излишне большое распределение.

Я говорю это потому, что эта строка в методе create_object arrayPtr = model; присваивает адрес памяти переданного triangle_t * 'model', для недавно выделенного arrayPtr.

Однако в строке выше этой вы выделили нагрузку памяти для адреса arrayPtr ... Это может привести к утечке памяти, так как вы выделяете память для этого адреса, а затем изменяете адрес указателя ( таким образом, он больше не указывает на , что памяти), но вы не обращаетесь к этой памяти бесплатно, поэтому он будет сидеть в куче на протяжении всей вашей программы.

Со строкой arrayPtr = model; Я подозреваю, что вы действительно хотите сделать - выполнить копию в памяти содержимого адреса модели, во вновь выделенный адрес arrayPtr. Поэтому на самом деле это должно выглядеть так:

memcpy(arrayPtr, model, sizeof(triangle_t) * numTriangles);

К сожалению, я не могу запустить ваш код, так как нахожусь на работе без доступа к компилятору C, однако, я подозреваю, что ваша ошибка вызвана тем, что вы освобождаете память от указателя модели, к которому все еще обращаются структурой object_t из-за случайного неправильного использования оператора присваивания '='.

0 голосов
/ 09 ноября 2018

Спасибо за помощь. Мой мыслительный процесс состоял в том, чтобы назначить указателю достаточно памяти для массива, а затем сделать копию установленного массива, назначив его указателю.

Во всяком случае, это сделало свое дело:

new_obj->model = malloc(sizeof(triangle_t)*numtriangles);
    if (new_obj == NULL)
        return NULL;
bcopy(model, new_obj->model, sizeof(triangle_t)*numtriangles);
0 голосов
/ 09 ноября 2018
// Assign values
arrayPtr = model;

То, что вы здесь делаете, это отбрасывает вновь выделенный указатель, содержащийся в arrayPtr, и просто назначаете его, чтобы он указывал на ту же память, что и model. Может произойти сбой, если model имеет более короткое время жизни (например, выделено в стеке) и больше не является действительным указателем после возврата функции.

Я полагаю, что вы хотели copy содержимого из массива модели в ваш новый массив, поэтому вы должны были сделать что-то вроде:

memcpy(arrayPtr, model, (sizeof(triangle_t))*numtriangles);
...