Динамическое выделение 2d массива в c ошибке - PullRequest
0 голосов
/ 06 марта 2019

Моя проблема предельно проста: я хочу выделить память для двумерного массива в c, заполнить его -1, затем освободить и выйти из программы.Мой код продолжает падать, и я не знаю, что я делаю неправильно ... Вот что я получил:

int main(){

    int i,j;
    char str1[]="xxxabxcxxxaabbcc";
    char str2[]="abc";
    int len1=strlen(str1);
    int len2=strlen(str2);

    printf("%d %d",len1,len2);

    //allocate 2d_array

    int **H_table = (int**)malloc((len1+1)*sizeof(int));
    for (i=0; i<len1+1; i++){
        H_table[i] = (int*)malloc((len2+1)*sizeof(int));
    }

    //fill and print 2d array

    for(i=0;i<len1+1;i++){
        for(j=0;j<len2+1;j++){
            printf("i:%d j:%d",i,j);
            H_table[i][j]=-1;
            printf(" value:%d\n",H_table[i][j]);
        }
    }

    // free 2d array

    for(i=0;i<len1;i++){
        free(H_table[i]);
    }
    free(H_table);
    return 0;
}

Итак, что я хочу выделить массив, который имеет 1 дополнительную строку и 1 дополнительный столбецчем две строки, если вы поместите их вертикально по сравнению друг с другом.

И это то, что я ожидал (вещи в скобках, очевидно, не являются частью таблицы, я положил их для сравнения):

   (x x x a b x c x x x a a b b c c)  
  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
a)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
b)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
c)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  

Проблема в том, что код падает при заполнении таблицы и всегда падает при i = 9 и j = 3 для этих конкретных строк.Странная часть в том, что если вы поменяете местами 2 строки (поместите «abc» в str1), то код пройдет этап заполнения и завершится с ошибкой при попытке освободить массив.

Извините за любые грамматические ошибки или переполнение стекаошибки, я вроде как новенький: P

Любая идея приветствуется :) спасибо заранее

Ответы [ 2 ]

1 голос
/ 06 марта 2019

Как указывало несколько человек, вы выделяете H_table с местом для len1 + 1 целых чисел , но на самом деле предполагается, что это массив len1 + 1 указателей (в целые числа).Так как указатели больше целых чисел (в любом случае, в вашей системе), вы получите неопределенное поведение из-за переполнения буфера.

Вот подсказка.Избегайте этой проблемы и множества других подобных проблем, всегда используя следующую модель для malloc:

some_variable = malloc(n * sizeof *some_variable);

Например:

int** H_table = malloc((len1 + 1) * sizeof *H_table);
for (int i = 0; i <= len1; ++i)
  H_table[i] = malloc((len2 + 1) * sizeof *H_table[i]);

То есть пусть компиляторвыяснить правильный тип для переменной (или lvalue).Компилятор менее подвержен опечаткам, чем вы, и если вы не напишете тип явно, вам будет намного проще принять решение, что H_table должно быть long или short или unsigned.

По той же причине не приводите явно приведенное значение malloc.C автоматически приводит void* к типу получателя и не выдает ошибку, если вы вручную приводите неверный тип.Так что просто дайте компилятору это сделать;он менее типизирован, безопаснее и более перспективен на будущее.

Обратите внимание, что если вы используете выражение с sizeof, компилятор не оценивает выражение [Примечание 1].Он просто вычисляет тип и подставляет его в выражение.Так что не беспокойтесь о дополнительных оценках: их нет.Вот почему можно использовать эту модель с объявлениями, даже если some_variable еще не имеет значения при выполнении malloc.


Примечания:

  1. Есть одно обстоятельство, при котором компилятор может вычислять ex в sizeof ex: если ex - массив переменной длины.Однако в этом случае ex всегда является указателем, поэтому применение в этом случае невозможно.
0 голосов
/ 06 марта 2019

Как отметил @xing в своем комментарии, H_table - указатель на указатель на целое число.поэтому вам нужно изменить int на int* в первом malloc.здесь:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){

    int i,j;
    char str1[]="xxxabxcxxxaabbcc";
    char str2[]="abc";
    int len1=strlen(str1);
    int len2=strlen(str2);

    printf("%d %d",len1,len2);

    //allocate 2d_array

    int **H_table = (int**)malloc((len1+1)*sizeof(int*));
    for (i=0; i<len1+1; i++){
        H_table[i] = (int*)malloc((len2+1)*sizeof(int));
    }

    //fill and print 2d array

    for(i=0;i<len1+1;i++){
        for(j=0;j<len2+1;j++){
            printf("i:%d j:%d",i,j);
            H_table[i][j]=-1;
            printf(" value:%d\n",H_table[i][j]);
        }
    }

    // free 2d array

    for(i=0;i<len1;i++){
        free(H_table[i]);
    }
    free(H_table);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...