Безопасное выделение структуры, содержащей различные массивы в c - PullRequest
5 голосов
/ 01 апреля 2011

У меня есть что-то подобное в моем коде

typedef struct ts_fem_mesh
{   
    double          **vertices;
    unsigned int    **triangles;
    unsigned int    n_ver;
    unsigned int    n_tri;
} fem_mesh;

fem_mesh *fem_mesh_new(unsigned int n_ver, unsigned int n_tri)
{
    fem_mesh *mesh;
    mesh = (fem_mesh *)malloc(sizeof(fem_mesh));

    mesh->n_ver = n_ver;
    mesh->n_tri = n_tri;

    mesh->vertices = (double **)calloc(n_ver, sizeof(double *));
    mesh->triangles = (unsigned int **)calloc(n_tri, sizeof(unsigned int *));

    int i;
    for(i=0;i<n_ver;i++)
        mesh->vertices[i] = (double *)calloc(2, sizeof(double));
    for(i=0;i<n_tri;i++)
        mesh->triangles[i] = (unsigned int *)calloc(3, sizeof(unsigned int));
    return mesh;

}

Обычно, когда я звоню fem_mesh_new, я использую очень большое число для n_ver и n_tri, что иногда приводит к ошибке выделения (недостаточно места).

Даже если я получу такую ​​ошибку, моя программа должна дать пользователю совет и выполнить его. В этом случае я хочу освободить все, что я выделил с момента ошибки (т.е. я получаю ошибку, когда пытаюсь выделить mesh->triangles, но mesh->vertices выделяется, поэтому я хочу освободить mesh->vertices)

Есть ли более простой способ сделать это? Единственный способ, которым я могу думать (это тот, который я хотел бы избежать), это заполнить мой код многих if (x == NULL) , но это очень раздражает из-за порядка, в котором выделяется память (в каждой точке, где я мог получить ошибку, мне нужно было написать код, который освобождает все объекты, выделенные с этой точки).

Не знаю, понятно ли, надеюсь, кто-нибудь может принести какую-нибудь помощь:)

Ответы [ 2 ]

2 голосов
/ 01 апреля 2011

Вам всегда нужно проверять возвращаемое значение malloc().

Я думаю, что это хорошее применение goto:

int foo(void) {
    a = malloc();
    if (!a) goto aerr;
    b = malloc();
    if (!b) goto berr;
    c = malloc();
    if (!c) goto cerr;
    d = malloc();
    if (!d) goto derr;

    /* ... use memory ... */

    free(d);
derr:
    free(c);
cerr:
    free(b);
berr:
    free(a);
aerr:
    return 0;
}
1 голос
/ 01 апреля 2011

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

после mesh = (fem_mesh *)malloc(sizeof(fem_mesh));

после mesh->triangles = (unsigned int **)calloc(n_tri, sizeof(unsigned int *)); и проверить оба распределения.

после ваших циклов и проверить в цикле.

...