Пытаюсь написать динамический массив со строками произвольной длинны, выдает следующую ошибку: Segmentation fault (core dumped)
#include <stdio.h>
#include <stdlib.h>
int main()
{
int** array2;
int* length;
int rows;
printf("put number of rows\n");
scanf("%d", &rows);
array2 = calloc(rows, sizeof(int*));
length = calloc(rows, sizeof(int));
for (int i = 0; i < rows; i = i + 1)
{
printf("put length %d row\n", i);
scanf("%d", &length[i]);
for (int j = 0; j < length[i]; j = j + 1)
{
printf("put %d number in %d row\n", j + 1, i + 1);
scanf("%d", &array2[i][j]);
}
}
printf("\n");
for (int i = 0; i < rows; i = i + 1)
{
for (int j = 0; j < length[i]; j = j + 1)
{
printf("%d\t", array2[i][j]);
}
free(array2[i]);
printf("\n");
}
free(array2);
free(length);
}
Не могу понять в чем тут ошибка, пытаюсь освоить динамическую память, а спросить некого
Ответы (1 шт):
Во-первых пропущено выделение памяти под каждую строку (очистка, кстати не забыта).
А во-вторых предлагаю заменить calloc
на malloc
, зачем нам терять время на инициализацию нулями, если все равно предстоит заполнять данными.
И, да простят меня любители красоты и порядка, приведу маленькую оптимизацию по выделению общей памяти для двух массивов. В данном примере это совершенно бесполезно, но когда массивов очень много, позволяет сократить время на выделение/очистку памяти.
А если они ещё и однотипные и с одинаковой длиной - позволяет в коде манипулировать адресами, а не работать с отдельными переменными.
#include <stdio.h>
#include <stdlib.h>
int main(){
int** array2;
int* length;
int rows;
printf("put number of rows\n");
scanf("%d", &rows);
//Мы знаем размеры массивов, так зачем выделять две области?
//Выделим одну и поделим на две части. И очищать будем одну.
length = (int*)malloc(rows*sizeof(int)+rows*sizeof(int*));
//Указатель на следующий после length элемент становится
//указателем на array2
array2 = (int**)&length[rows];
//или так: array2 = (int**)(length+rows);
//или так: array2 = (int**)((char*)length+rows*sizeof(int));
for (int i = 0; i < rows; i++){
printf("put length %d row\n", i);
scanf("%d", &length[i]);
array2[i] = (int*)malloc(length[i]*sizeof(int));
for (int j = 0; j < length[i]; j = j + 1){
printf("put %d number in %d row\n", j + 1, i + 1);
scanf("%d", &array2[i][j]);
}
}
printf("\n");
for (int i = 0; i < rows; i = i + 1){
for (int j = 0; j < length[i]; j = j + 1){
printf("%d\t", array2[i][j]);
}
free(array2[i]);
printf("\n");
}
//free(array2);
free(length);
return 0;
}
https://godbolt.org/z/PGax9z76W
Кроме того, если объемы данных небольшие, и вы уверены в том, что не переполните стек, можно для первых двух массивов выделить место прям в стеке, по месту так сказать:
int main(){
int rows;
printf("put number of rows\n");
scanf("%d", &rows);
int *array2[rows];
int length[rows];
...
Выделение памяти в стеке намного быстрее и обращение тоже чуть-чуть быстрее. Кроме того, можно не освобождать выделенную память. Только надо помнить, что для функции main()
- это выделение памяти на всё время работы программы и пользы опять таки не очень то и много, а для мелких функций, которые поработали и вернулись - самое то.
Можно пойти ещё дальше, использовать alloca()
, динамически выделяющую память в стеке, но тут нужен некоторый опыт и понимание чем это грозит.