my program fails always in the 4th realloc and I don't understand why it makes the 3 first good and then it fails. I'm using triple pointer and I've tried to debugate and all works good until the 4th realloc when it says that its out of scope and segmention fault.
#include <stdio.h>
#include <stdlib.h>
void rellenar(int ***movimiento, int mov, int discos) {
int j, pos, mov2, ***movimiento2;
mov2 = mov + 1;
movimiento = realloc(movimiento, mov2 * sizeof (int **));
movimiento[mov] = malloc(3 * sizeof (int *)); //3 de torres
for (j = 0; j < 3; ++j) {
movimiento[mov][j] = malloc(discos);
}
printf("%d\n", mov);
for (pos = 0; pos < discos; pos++) {
movimiento[mov][0][pos] = 1;
movimiento[mov][1][pos] = 1;
movimiento[mov][2][pos] = 1;
printf("%d", movimiento[mov-1][0][pos]);
printf("%d", movimiento[mov-1][1][pos]);
printf("%d\n", movimiento[mov-1][2][pos]);
}
}
int main(int argc, char** argv) {
int ***movimiento, i, j, movs = 1, discos = 4, pos, mov;
movimiento = malloc(movs * sizeof (int **));
for (i = 0; i < movs; ++i) {
movimiento[i] = malloc(3 * sizeof (int *)); //3 de torres
for (j = 0; j < 3; ++j) //3 de torres
{
movimiento[i][j] = malloc(discos);
}
}
for (pos = 0; pos < discos; pos++) {
movimiento[0][0][pos] = discos - pos;
movimiento[0][1][pos] = 0;
movimiento[0][2][pos] = 2;
}
for (pos = 0; pos < discos; pos++) {
printf("%d", movimiento[0][0][pos]);
printf("%d", movimiento[0][1][pos]);
printf("%d\n", movimiento[0][2][pos]);
}
for (mov = 1; mov < 6; mov++) {
rellenar(movimiento, mov, discos);
}
}
What's wrong?
Rather than triple-nested mallocs and reallocs, which are inefficient and hard to keep straight, just do your allocation in a single shot:
size_t total = mov2 * 3 * discos;
int* movimiento = malloc(total * sizeof(int));
Now you can fill it like this:
for (size_t ii = 0; ii < total; ++ii)
movimiento[ii] = 1;
Then make an indexing function:
int* get_cell(int* matrix, size_t x, size_t y, size_t z, size_t max_y, size_t max_z) {
return &matrix[x*max_y*max_z + y*max_z + z];
}
So then:
int two = *get_cell(movimiento, mov, 1, pos, 3, discos);
And when it's time to release the memory, it's simply:
free(movimiento);
Related
I am trying to solve the Dynamic Array problem of Hackerrank in C. I tried so many ways but all in vain. The best I could do is to clear 4 test cases. I am getting a segmentation error. Please help me find where am I doing wrong. It will be really helpful.
Question Link: https://www.hackerrank.com/challenges/dynamic-array/problem
We are supposed to complete the function. So here is my attempt:
int *dynamicArray(int n, int queries_rows, int queries_columns, int **queries,
int *result_count) {
*result_count = 0;
int *result = (int *)malloc(queries_rows * sizeof(int));
int i = 0, j = 0, y, x;
int lastAnswer = 0;
int **arr = (int **)malloc(n * sizeof(int *));
int *size = (int *)malloc(n * sizeof(int));
for (i = 0; i < n; i++) {
size[i] = 0;
}
for (i = 0; i < n; i++) {
arr[i] = (int *)malloc(n * sizeof(int));
}
for (i = 0; i < queries_rows; i++) {
x = queries[i][1];
y = queries[i][2];
if (queries[i][0] == 1) {
size[(x ^ lastAnswer) % n]++;
arr[(x ^ lastAnswer) % n][size[(x ^ lastAnswer) % n] - 1] = y;
} else {
lastAnswer = arr[(x ^ lastAnswer) % n][y % size[(x ^ lastAnswer) % n]];
printf("%d\n", lastAnswer);
(*result_count)++;
result[(*result_count) - 1] = lastAnswer;
}
}
result = (int *)realloc(result, (*result_count) * sizeof(int));
return result;
}
Your implementation is a little too complicated: you should use an intermediary variable idx as specified in the problem statement:
Create a 2-dimensional array arr, of n empty arrays. All arrays are zero indexed.
Create an integer lastAnswer, and initialize it to 0.
There are types of queries:
Query: 1 x y
Find the list within arr at index idx = (x ^ lastAnswer) % n.
Append the integer y to the arr[idx].
Query: 2 x y
Find the list within arr at index idx = (x ^ lastAnswer) % n.
Find the value of element y % size(arr[idx]) where size is the number of elements in arr[idx], Assign the value to lastAnswer.
Print the new value of lastAnswer on a new line.
Assuming the function prototype is correct, here is a simpler version:
int *dynamicArray(int n, int queries_rows, int queries_columns, int **queries,
int *result_count) {
int **arr = (int **)malloc(n * sizeof(int *));
int *size = (int *)calloc(n * sizeof(int));
int *result = (int *)malloc(queries_rows * sizeof(int));
int i, j;
int count = 0;
int lastAnswer = 0;
for (i = 0; i < n; i++) {
arr[i] = (int *)malloc(n * sizeof(int));
}
for (i = 0; i < queries_rows; i++) {
int x = queries[i][1];
int y = queries[i][2];
int idx = (x ^ lastAnswer) % n;
if (queries[i][0] == 1) {
arr[idx][size[idx]++] = y;
} else {
lastAnswer = arr[idx][y % size[idx]];
printf("%d\n", lastAnswer);
result[count++] = lastAnswer;
}
}
*result_count = count;
for (i = 0; i < n; i++) {
free(arr[i]);
}
free(arr);
free(size);
return (int *)realloc(result, count * sizeof(int));
}
The problem with this implementation is the size of the lists in the array arr may grow larger than n. You should therefore reallocate them as you append values.
Here is a modified version:
int *append_list(int **list, int size, int value) {
*list = realloc(*list, (size + 1) * sizeof(int));
(*list)[size] = value;
return p;
}
int *dynamicArray(int n, int queries_rows, int queries_columns, int **queries,
int *result_count) {
int **arr = (int **)malloc(n * sizeof(int *));
int *size = (int *)calloc(n * sizeof(int)); // initializes to 0
int *result = NULL;
int i, j;
int count = 0;
int lastAnswer = 0;
for (i = 0; i < n; i++) {
arr[i] = NULL;
}
for (i = 0; i < queries_rows; i++) {
int x = queries[i][1];
int y = queries[i][2];
int idx = (x ^ lastAnswer) % n;
if (queries[i][0] == 1) {
append_list(&arr[idx], size[idx]++, y);
} else {
lastAnswer = arr[idx][y % size[idx]];
printf("%d\n", lastAnswer);
append_list(&result, count++, lastAnswer);
}
}
for (i = 0; i < n; i++) {
free(arr[i]);
}
free(arr);
free(size);
*result_count = count;
return result;
}
I am trying to return a contiguous memory allocated array from a function but I keep on receiving errors.
Compiler returns a warning saying return from incompatible pointer type [-Wincompatible-pointer-types]
Can someone tell me what I am doing wrong?
int *test() {
size_t rows, cols;
// assign rows and cols
rows = 3;
cols = 3;
int count = 0;
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr) {
// do stuff with arr[i][j]
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; j++) {
arr[i][j] = count;
count++;
}
/* code */
}
}
return arr;
}
int main() {
size_t rows, cols;
// assign rows and cols
rows = 3;
cols = 3;
int count = 0;
int (*arr)[cols] = malloc(sizeof *arr * rows);
arr = test();
int i = 0;
int j = 0;
for (i = 0; i < rows; ++i) {
for (j = 0; j < 3; ++j)
printf("%d ", arr[i][j]);
printf("\n");
}
free(arr);
}
it should return a 2D array but returns an error and am using gcc on ubuntu
Your allocation function is fine, except for a few details:
you should pass rows and cols as arguments
you should use type size_t for i and j and iterate to rows and cols instead of hard coded bounds.
you should use parentheses in malloc(sizeof *arr * rows); for readability:
malloc(sizeof(*arr) * rows);
you should return &arr[0][0] or arr[0] for type correctness.
The problem is you cannot define the return type of test to be pointer to 2D array of a parametric second dimension. Hence the type error on the assignment arr = test(); cannot be fixed. You can work around this shortcoming by casting the return value to (int (*)[cols]) or simply (void *).
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int *test(size_t rows, size_t cols) {
int (*arr)[cols] = malloc(sizeof(*arr) * rows);
if (arr) {
// initialize the matrix
size_t count = 0;
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
arr[i][j] = count;
count++;
}
/* code */
}
return &arr[0][0];
}
return NULL;
}
int main() {
// assign rows and cols
size_t rows = 3;
size_t cols = 3;
int (*arr)[cols] = (int (*)[cols])test(rows, cols);
if (arr) {
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
free(arr);
}
return 0;
}
Output:
0 1 2
3 4 5
6 7 8
If all what you need is
to return a contiguous memory allocated array from a function
You can ignore this answer.
If what you are trying to do is to model a bidimensional container (like a matrix) using a dynamically allocated contiguous block of memory, you could define a struct and pass that around:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct {
int rows, cols;
int values[]; // I'm using a Flexible Array Member here.
} iMat;
iMat *alloc_matrix(int rows, int columns)
{
assert(rows > 0 && columns > 0);
iMat *tmp = malloc(sizeof *tmp + sizeof *(tmp->values) * rows * columns);
if (tmp)
{
tmp->rows = rows;
tmp->cols = columns;
}
return tmp;
}
void fill_matrix_iota(iMat *m, int start)
{
if ( m )
for (size_t i = 0, n = m->rows * m->cols; i < n; ++i)
m->values[i] = start + i;
}
void print_matrix(iMat *m, int width)
{
if (m)
{
for (int i = 0, k = 0; i < m->rows; ++i)
{
for(int j = 0; j < m->cols; ++j, ++k)
{
printf("%*.d", width, m->values[k]);
}
putchar('\n');
}
}
}
iMat *make_transposed(iMat *m)
{
if ( !m )
return NULL;
iMat *tmp = alloc_matrix(m->cols, m->rows);
if ( tmp )
{
for (int i = 0; i < m->rows; ++i)
{
for(int j = 0; j < m->cols; ++j)
{
tmp->values[j * m->rows + i] = m->values[i * m->cols + j];
}
}
}
return tmp;
}
int main(void)
{
iMat *a = alloc_matrix(3, 4);
if (!a)
exit(EXIT_FAILURE);
fill_matrix_iota(a, 1);
print_matrix(a, 3);
iMat *b = make_transposed(a);
if (!b)
{
free(a);
exit(EXIT_FAILURE);
}
putchar('\n');
print_matrix(b, 3);
free(b);
free(a);
return EXIT_SUCCESS;
}
Can't increase rows in 2d array, but columns is ok.
#include <stdio.h>
#include <stdlib.h>
it is working:
void increasecolumn(int ** mas, int* n, int m){
for (int i = 0; i < m; i++){
int* tmp = realloc(mas[i], sizeof (*mas[i]) * ((*n) + 1));
if (tmp){
mas[i] = tmp;
}
}
(*n) = (*n) + 1;
}
but increasing rows failed
void increaserow(int ** mas, int n, int* m){
int ** tmp = realloc(mas, sizeof(*mas) * ((*m) + 1));
if (tmp){
mas = tmp;
for (int i = 0; i < 1; i++){
mas[(*m) + i] = malloc(sizeof(*mas[(*m) + i]) * n);
}
}
(*m) = (*m) + 1;
}
int main(int argc, char * argv[]) {
int n = 3; // columns
int m = 2; // rows
int** mas = malloc(m*sizeof(*mas));
for(int i = 0; i < m; i++){
mas[i] = malloc(n*sizeof(*(mas[i])));
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
mas[i][j] = 0;
printf("%d ", mas[i][j]);
}
printf("\n");
}
printf("\n");
increasecolumn(mas, &n, m);
for (int i = 0; i < m; i++){
mas[i][n-1] = 1;
}
increaserow(mas, n, &m); // problem is here
for (int j = 0; j < n; j++){
mas[m-1][j] = 0;
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
printf("%d ", mas[i][j]);
}
printf("\n");
}
system("pause");
return 0;
}
I use this answer Resizing 2D Arrays in C like an example, something wrong.
The GNU Project Debugger on Windows:
warning: FTH: (9152): * Fault tolerant heap shim applied to current process. This is usually due to previous crashes. *
0 0 0
0 0 0
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401821 in main (argc=1, argv=0x7f1990) at D:\III Курс! II СЕМЕСТР\МатМодДослОп\stud\Untitled2.c:47
47: mas[m-1][j] = 0;
#include <stdio.h>
#include <stdlib.h>
void printingArr(int** arr, int rows);
void sortingEachOneOfThem(int** pArr, int rows);
void sortingTheWholeArray(int** pArr, int rows);
void bubbleSort(int* arr);
void freeArray(int **a, int m);
int main(void)
{
int** pArr = 0;
int numOfRows = 0;
int sizes = 0;
printf("Enter number of rows: ");
scanf("%d", &numOfRows);
pArr = (int**) malloc(sizeof(int*) * numOfRows);
if (pArr == NULL)
{
printf("Unsuccessful malloc!\n");
return 1;
}
for (int i = 0; i < numOfRows; i++)
{
printf("Enter array length for row %d: ",i);
scanf("%d", &sizes);
pArr[i] = (int*) malloc(sizeof(int) * sizes + 1);
if (pArr[i] == NULL)
{
printf("Unsuccessful malloc!\n");
return 1;
}
pArr[i][0] = sizes;
for (int k = 1; k < sizes + 1; k++)
{
printf("Enter value for array: ");
scanf("%d", &pArr[i][k]);
}
}
printingArr(pArr, numOfRows);
sortingEachOneOfThem(pArr, numOfRows);
printingArr(pArr, numOfRows);
sortingTheWholeArray(pArr, numOfRows);
printingArr(pArr, numOfRows);
for (int i = 0; i < numOfRows; i++)
{
if (pArr[i] != NULL)
{
free(*(pArr + i));
}
}
//free(pArr);
system("pause");
return 0;
}
/*
this amazing, wonderfull piece of program prints the array given
input: int** arr, int rows
output: none
*/
void printingArr(int** arr, int rows)
{
int i = 0;
int k = 0;
for (i = 0; i < rows; i++)
{
for (k = 0; k <= arr[i][0]; k++)
{
printf("%d ", arr[i][k]);
}
printf("\n");
}
printf("\n");
}
/*
This beautiful function sorts the whole array, but its length of rows like a pyramid
input: int** arr, int rows
output: none
*/
void sortingTheWholeArray(int** pArr, int rows)
{
int* temp = 0;
int i = 0, k = 0;
for (i = 0; i < rows - 1; i++)
{
for (k = 0; k < rows - 1; k++)
{
if (pArr[k][0] > pArr[k + 1][0])
{
temp = pArr[k];
pArr[k] = pArr[k + 1];
pArr[k + 1] = temp;
}
}
}
}
/*
This little small function sorts every row of the array of arrays given to it
input: int** arr, int rows
output: none
*/
void sortingEachOneOfThem(int** pArr, int rows)
{
int i = 0;
for (i = 0; i < rows; i++)
{
bubbleSort(pArr[i]);
}
}
/*
This little piece of a code is a bubble sort, sorts the array given to it :)
input: int* arr, int rows
output: none
*/
void bubbleSort(int* arr)
{
int i = 1, k = 0;
for (i = 1; i < arr[0] - 1; i++)
{
for (k = 1; k <= arr[0] - i; k++)
{
if (arr[k] > arr[k + 1])
{
arr[k] += arr[k + 1];
arr[k + 1] = arr[k] - arr[k + 1];
arr[k] -= arr[k + 1];
}
}
}
}
the free at the end crashes my code, showing this error:
https://i.stack.imgur.com/nqxBG.png
the same usage of the function free() on another code worked good, but not here. I have tried running through it in step by step mode, it crashes at the first free. Dr. memory shows this: https://i.stack.imgur.com/rSZJr.png
another link: https:// i.stack. imgur.com/ZX2Ne.png (paste it without the spaces in the middle, Can't post more than 2 links)
what can I do?
This:
pArr[i] = (int*) malloc(sizeof(int) * sizes + 1);
under-allocates. Adding a single byte to the size of an array of int makes little sense. You probably meant:
pArr[i] = malloc((sizes + 1) * sizeof *pArri[i]);
Don't cast the return value of malloc(), and use sizeof on the left-hand side.
int ** ARR;
int LENGTH = 1;
int DEPTH = 1;
void loadt(int ** terr)
{
terr = (int**)malloc(sizeof(int*) * (LENGTH + 1));
int i, j;
for(i = 1; i <= LENGTH; i++)
terr[i] = (int*)malloc(sizeof(int) * (DEPTH + 1));
for(i = 1; i <= LENGTH; i++)
for(j = 1; j <= DEPTH; j++)
scanf("%d", &terr[i][j]);
}
void freet(int ** terr)
{
int i;
for(i = 1; i <= LENGTH; i++){
free(terr[i]);
}
free(terr);
}
int main(int argc, char* argv[])
{
loadt(ARR);
freet(ARR);
return 0;
}
Hello. I probably miss sth really basic here but after I run the program it crashes."Segmentation fault (core dumped)" Why?
Because in c arguments to functions are always passed by value, so your unecessarily global variable is not getting reassigned inside the function since you are passing it as a parameter and hence a copy of it is made, which is the one that is actually reassigned.
So you are calling free() on an uninitialized poitner.
Try like this
int **loadt(int LENGTH, int DEPTH)
{
int **terr;
int i, j;
terr = malloc(sizeof(int*) * (LENGTH + 1));
if (terr == NULL)
return NULL;
for (i = 1; i <= LENGTH; i++) {
terr[i] = malloc(sizeof(int) * (DEPTH + 1));
if (terr[i] == NULL) {
for (j = i ; j >= 0 ; --j) {
free(terr[j]);
}
free(terr);
return NULL;
}
}
for (i = 1; i <= LENGTH; i++) {
for (j = 1; j <= DEPTH; j++) {
scanf("%d", &terr[i][j]);
}
}
return terr;
}
void freet(int **terr)
{
int i;
if (terr == NULL)
return; // `free()' also accepts NULL pointers
for (i = 1; i <= LENGTH; i++) {
free(terr[i]);
}
free(terr);
}
int main(int argc, char* argv[])
{
int **ARR;
int LENGTH = 1;
int DEPTH = 1;
ARR = loadt(LENGTH, DEPTH);
freet(ARR);
return 0;
}
Another problem, is that you start your loops at i = 1, which is fine because you are allocating enough space, but it's not the way you should do it. Instead for (i = 0 ; i < LENGTH ; ++i) would be how a c programmer would do it. Note that you are wasting the first element of your array.