Массив обозначений для указателей - PullRequest
3 голосов
/ 06 июня 2019

Я сделал функцию, которая возвращает указатель на вновь созданную матрицу.Теперь я хочу, чтобы эта функция возвращала код ошибки типа status_t вместо указателя.Для этого необходимо добавить еще один уровень указателя и вернуть матрицу по ссылке.Однако я не могу понять, почему появляется ошибка сегментации.Вот часть моего рабочего кода (а) и моей неудачной попытки (б):

(а)

int **create_matrix(size_t dimension) {
    int **p;
    size_t e;
    size_t h;

    if (dimension == 0)
        return NULL;

    for (h = 0; h < dimension; ++h) {
        if ((p[h] = malloc(dimension * sizeof(int))) == NULL) { 
            for (e = h; e >= 0; --e) {  
                free(p[e]);
                p[e] = NULL;
            } <-------- missing closing brace
            return NULL;
        }
    }
    return p;
}

(б)

status_t create_matrix(size_t dimension, int ***p) {
    size_t e;
    size_t h;

    if (p == NULL)
        return ERROR_NULL_POINTER;

    for (h = 0; h < dimension; ++h) {
        if (((*p)[h] = malloc(dimension * sizeof(int))) == NULL) { 
            for (e = h; e >= 0; --e) {  
                free((*p)[e]);
                (*p)[e] = NULL;
            } <-------- missing closing brace
            return ERROR_NO_MEMORY;
        }
    }
}

спасибо!

1 Ответ

4 голосов
/ 06 июня 2019

(a) не совсем "работает":

Во-первых, у него больше {, чем }, поэтому он даже не компилируется.Вы, вероятно, забыли завершить свой внешний цикл for.

int ** p;
...
    if ((p[h]=...))

Это разыменовывает p до его инициализации.Использование значения неинициализированной переменной является неопределенным поведением.Вам нужно назначить что-то для p, прежде чем использовать его (возможно, путем динамического выделения другого массива).

Чтобы определить, есть ли у версии (b) такая же проблема, мы должны увидеть вызывающий код,но, по-видимому, это также UB.

Есть еще одна проблема во внутреннем цикле:

        for (e = h; e >= 0; --e)

e - это size_t, который является целым типом без знака, поэтому условиеe >= 0 всегда верно.

Какой компилятор (и опции компилятора) вы используете?С gcc -Wall -Wextra -pedantic я получаю предупреждения для обоих этих .

Фиксированная версия будет выглядеть следующим образом:

int **create_matrix(size_t dimension) {
    int **p = calloc(dimension, sizeof *p);
    if (!p) {
        return NULL;
    }

    for (size_t i = 0; i < dimension; i++) {
        if (!(p[i] = calloc(dimension, sizeof *p[i]))) {
            while (i--) {
                free(p[i]);
            }
            free(p);
            return NULL;
        }
    }

    return p;
}

Версия (b) может быть определена как

status_t create_matrix_2(size_t dimension, int ***p) {
    if (!p) {
        return ERROR_NULL_POINTER;
    }
    if (!(*p = create_matrix(dimension))) {
        return ERROR_NO_MEMORY;
    }
    return SUCCESS_OR_SOMETHING;
}

Я не уверен, что вы хотите вернуть для успеха;в вашей версии (b) отсутствует инструкция возврата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...