Nick_is_asking Ответов: 4

2D массив в C -> segmentation fault (core dumped)


Привет, ребята...
Я использую C для создания 2d-массива без полного успеха.Я получаю следующую ошибку:
Segmentation fault (core dumped)


Объяснение кода:

Сначала я даю строки и cols через вход, а затем печатаю 2d_array со случайными числами от 1 до 100.
Когда print_2d_array (.....) собирается запустить, я получаю вышеуказанную ошибку.

Код:

Что я уже пробовал:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int rows_col(char *str);
int randomness();
void print_2d_array(int **array , int rows , int cols);

int main(void)
{
    srand(time(NULL));
    int **array_2d;
    int rows = rows_col("rows");
    int cols = rows_col("columns");
    array_2d = malloc(sizeof(int) * rows * cols);
    print_2d_array(array_2d , rows , cols);
    printf("\n\n\n");
    free(array_2d);
}


int rows_col(char str[10])
{
    int num = 1;
    printf("Give the number of %s: " , str);
    do
    {
        if(num <= 0)
        {
            printf("This is a negative/zero number.Please try again.\n");
            printf("Give the number of %s: " , str);
        }
        scanf("%d" , &num);
    }
    while(num <= 0);
    return num;
}


int randomness()
{
    return ( (rand() % 100) + 1);
}



void print_2d_array(int **array , int rows , int cols)
{    
    for(int i = 0; i < cols; i++)
    {
        for(int j = 0; j < rows; j++)
        {
            array[i][j] = randomness();
            printf("%d\t" , array[i][j]);
        }
        printf("\n");
    }
}



Я хочу, чтобы вы помогли найти/решить эту проблему.
Заранее спасибо!!!

jeron1

Одна вещь,

Скрыть   скопировать код

    while(num <= 0);


Как только этот цикл начинается, он не останавливается (бесконечный цикл).


редактировать: полный brainfart.

OriginalGriff

Нет, это конец света. do { ... } while (num <=0);

jeron1

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

Nick_is_asking

Я не согласен ,потому что ,когда приходит оператор do, вызывается scanf, поэтому он ждет пользователя, а затем проверяет номер.Вот как работает do while
Я проверил его, и он работает, как я и ожидал.

jeron1

Дох! Вы абсолютно правы, мои извинения! видимо, мой кофеиновый кайф прошел.

k5054

обратите внимание, что вы столбцы/строки задом наперед: если вы просите 5 строк и 3 столбца, вы на самом деле распечатываете 3 строки по 5 столбцов в каждой.

4 Ответов

Рейтинг:
1

Patrice T

Насколько я помню,

int **array_2d;

вы объявляете указатель на список указателей на списки целых чисел.
Но здесь,
array_2d = malloc(sizeof(int) * rows * cols);

malloc создает список целых чисел и возвращает указатель на этот список, а указатель, возвращаемый malloc, не знает, что вам нужен 2d-массив.
Вы не соответствуете типу массива и распределению памяти.

//A chunk of memory is basically 1D
0 1 2 3 4 5 6 7 8
// but with a little logic, it is 2D
0 1 2 // row 0
3 4 5 // row 1
6 7 8 // row 2
// the logic to convert 2D to 1D is
position= row * cols + col;


Рейтинг:
1

OriginalGriff

Что вам нужно сделать, так это посмотреть, что происходит во время выполнения вашего кода.
К счастью, у вас есть инструмент, который поможет вам выяснить, что происходит: отладчик. Как вы его используете, зависит от вашей системы компилятора, но быстрый поиск в Google имени вашей IDE и "отладчика" должен дать вам необходимую информацию.

Поместите точку останова в первую строку функции и запустите код через отладчик. Затем посмотрите на свой код и на свои данные и определите, что должно произойти вручную. Затем по одному шагу в каждой строке проверяйте, что то, что вы ожидали, произойдет именно так, как и произошло. Когда это не так, тогда у вас есть проблема, и вы можете вернуться назад (или запустить ее снова и посмотреть более внимательно), чтобы выяснить, почему.

Извините, но мы не можем сделать это за вас - пришло время вам освоить новый (и очень, очень полезный) навык: отладку!


Рейтинг:
1

Rick York

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

// release function for the 2D array allocator

void **Free2DArray( void **array, int xdim )  // xdim is the number of rows
{
    int x;

    if( array == NULL )
        return NULL;        // sanity check

    // release each row in reverse order of allocation
 
    for( x = xdim - 1; x >= 0; x-- )
    {
        if( array[ x ] )
        {
            free( array[ x ] );
            array[ x ] = NULL;
        }
    }

    // release the pointer to the row pointers

    free( array );
    return NULL;
}

// a general 2D array allocator - array is accessed as : array[ x ][ y ]
// example : int ** array = Alloc2DArray( rows, sizeof( int * ), cols, sizeof( int ) );
// a macro to help :
#define Allocate2D( r, c, t ) Alloc2DArray( r, sizeof( t * ), c, sizeof( t ) )
// example : int ** array = Allocate2D( rows, columns, int );

void ** Alloc2DArray( int xdim, int xitmsize, int ydim, int yitmsize )
{
    int     i;
    int     x;
    void ** data;

    // allocate a pointer to the pointers to each row of data

    data = (void **)calloc( xdim, xitmsize );
    if( data == NULL )
        return NULL;

    // now allocate each row

    for( x = 0; x < xdim; x++ )
    {
        data[x] = calloc( ydim, yitmsize );
        if( data[x] == NULL )
        {
            Free2DArray( data, xdim );  // release what we got
            return NULL;                // and bail out
        }
    }

    return data;
}


Рейтинг:
0

k5054

У вас есть декларация:

int **array_2d;
Это провозглашает array_2d как pointer to pointer to int. Но затем вы выделяете массив с помощью
array_2d = malloc(sizeof(int) * rows * cols)
. Этот malloc() возвращает непрерывный блок памяти (т. е. int *, который не является pointer to pointer to int
У вас есть 2 варианта:
1) выделите массив из int * то есть rows долго, а затем выделите массив int то есть cols длинный для каждого ряда
int **array_2d;
array_2d = malloc(sizeof(int*) * rows); // This creates an array of pointers to int
for(int i = 0; i < rows; ++i) {
    array_2d[i] = malloc(sizeof(int) * cols); // This creates a row of ints and asigns it to array_2d[i]
}


2) поскольку вы используете ubuntu и GCC, вы можете использовать расширения gnu и динамически изменять размер массива в print_2d_array()
void print_2d_array(void *ptr, int rows, int cols)
{
    int (*array)[rows] = ptr;  /* dynamically size array based on rows !! */
    for(int = 0; i < cols; ++i)
    {
        /* your code  here as before */
    }
}

В этом случае вам не нужно изменять свое распределение array_2d в main()