If i have a 2D array allocated as follows:
int** map;
map = malloc(number * sizeof(int*));
if(!(map)){
printf("out of memory!\n");
return 1;
}
for (int i = 0; i < number; i++){
map[i] = malloc(number * sizeof(int));
if (!(map[i])){
printf("Not enough memory!\n");
return 1;
}
}
If the allocation fails and we enter in the if statement should i free map and the "columns" allocated until now? If so, how should i do it?
Right now i just print the message and return 1 but i'm not sure if this is the correct approach.
Yes, you should free() otherwise you leak memory which might matter if this is in a long-running program.
One way to make it easier is to compute the total size of all the allocations, and do a single larger malloc() rather than a whole bunch of smaller ones. This is also (potentially much) faster, since heap allocations can be expensive.
That way, you only need to check once if it succeeded or failed, and there's nothing to free() in case of failure.
Something like this:
int ** map_allocate(size_t number)
{
int **base = malloc(number * sizeof (int *) + number * number * sizeof (int));
if(base != NULL)
{
int *row = (int *) (base + number);
for(size_t i = 0; i < number; ++i)
base[i] = row + i * number;
}
return base;
}
I didn't test-run this, but something along those lines.
You can use:
if (!(map[i])){
printf("Not enough memory!\n");
while (--i>=0)
free(map[i]);
free(map);
return 1;
}
Always set pointers to null immediately you allocate them.
int **map;
map = malloc(number * sizeof(int *));
if(!map)
goto out_of_memory;
for(i=0;i<number;i++)
map[i] = 0;
for(i=0;i<numbers;i++)
{
map[i] = malloc(number * sizeof(int));
if(!map[i])
goto out_of_memory;
}
...
return 0;
out_of_memory:
if(map)
for(i=0;i<number;i++)
free(map[i]);
free(map);
return -1;
Related
int* dynamicArray(int n, int queries_rows, int queries_columns, int** queries, int* result_count) {
int i,j;
int lastAnswer = 0,y,resultCount = 0;
int *result = NULL;
int **seqList = (int**) calloc (n,sizeof(int*));
for (i=0; i<queries_rows;i++)
{
y = (queries[i][1] ^ lastAnswer)% n;
if(queries[i][0] == 1){
if(seqList[y]==NULL){
int *dummy = (int*) calloc (2,sizeof(int));
seqList[y]=dummy;
}
for(j=0;j<n;j++){
if(seqList[y][j])
continue;
else {
printf("%d %d entry %d",y,j,seqList[y][j]);
seqList[y][j] = queries[i][2];
}
}
}
if(queries[i][0] == 2){
lastAnswer = seqList[y][queries[i][2]];
resultCount++;
if(result == NULL)
result = (int*) calloc (1,sizeof(int));
else {
result = (int*) realloc (result,resultCount * sizeof(int));
}
result[resultCount - 1] = lastAnswer;
}
}
*result_count = resultCount;
return result;
}
Anything wrong with the above realloc usage for giving out a "segfault"?
Is this the right way to use realloc?
Also running a debugger is not possible as this is a function completion of cooding site?
You are missing a few spots to "derive" a pointer to do any sort of action with the value...so you're probably trying to allocate/reallocate dynamic memory with the integers memory address instead of the value of the pointer(which would be deriving it).
Try putting an asterisk in front of the pointer variables when allocating/reallocating the memory.
Note these lines
int **seqList = (int**) calloc (n,sizeof(int*));
for (i=0; i<queries_rows;i++)
{
y = (queries[i][1] ^ lastAnswer)% n; // <-- ?
if(queries[i][0] == 1) {
if(seqList[y]==NULL) {
int *dummy = (int*) calloc (2, sizeof(int));
// ^^^
seqList[y]=dummy;
// ^^^
}
for( j = 0; j < n; j++ ) {
// ^^^^^ is n bigger than 2?
if( seqList[y][j] )
// ^^^
continue;
else {
// ...
seqList[y][j] = queries[i][2];
// ^^^
}
}
}
According to what the OP commented "n will be till 10^5", but only enough memory to store a couple of ints has been allocated.
Also note that both calloc and realloc may fail, but none of the values returned by those functions are checked.
Further references to address other issues
Do I cast the result of malloc?
calloc with structure with pointers
Proper usage of realloc
so basically there is a function that allocates a new pointer memory and when i try to delocate the old one the program basically crashes my code
char** AddingToTheBook(char** original, int* size, char *number)
{
char** newArray = (char**)malloc(sizeof(char*)*(*size));
//allocating and copying the values
for (int i = 0; i < *size; i++)
{
*(newArray + i) = (char*)malloc(sizeof(char)*(strlen(*(original + i))));
strcpy(*(newArray + i), *(original + i));
}
//allocating a new memory to the new number
*(newArray + (*size)) = (char*)malloc(sizeof(char)*strlen(number));
strcpy(*(newArray + (*size)), number);
(*size)++;
//delocating the allocated memories
for (int i = 0; i < size; i++)
free(original[i]);
free(original);
return newArray;
}
You are freeing too much of your original memory.
Look at the for loop when you're freeing the memory:
(*size)++;
//delocating the allocated memories
for (int i = 0; i < size; i++)
free(original[i]);
Since size is a int * you will end up with a very big number of iterations which will free to free much more memory than you allocated. To fix this do the following:
(*size)++;
//delocating the allocated memories
for (int i = 0; i < *size; i++)
free(original[i]);
Now you're still freeing one element too much since you've incremented *size when adding a new element. The final version to free the original memory is
(*size)++;
//delocating the allocated memories
for (int i = 0; i < *size - 1; i++)
free(original[i]);
strlen only returns the number of chars. Make room for the ending zero
*(newArray + i) = (char*)malloc(sizeof(char)*(strlen(*(original + i))) +1);
Better to strncpy instead of strcpy
How can you go *size ahead in newArray:
*(newArray + (*size)) = (char*)malloc(sizeof(char)*strlen(number));
You can only go *size -1 ahead, since it starts from zero.
In the for loop, it seems you forgot to add the asterisk *
for (int i = 0; i < size; i++)
You can use realloc instead
char** AddingToTheBook(char** original, size_t oldsize, char *number)
{
char** tmp = realloc(**original, (oldsize + 1) * sizeof(char *));
if(tmp)
{
tmp[oldsize] = malloc(strlen(number) + 1'
if(tmp[oldsize])
{
strcpy(tmp[oldsize], number);
}
else
{
/* do something for example realloc back to the old size */
tmp = NULL;
}
}
return tmp;
}
example correct usage
char **tmp = AddingToTheBook(book, size, "Test String")
if(tmp)
{
book = tmp;
size++;
}
else
{
/* do something adding to book failed */
}
What should I consider thinking about when understanding the output? Because right now my output is garbage for 20 integers and I dont know why. MY objective is to create 20 arrays with 30 integers in each one. So the final array will have integers of 19 to 48.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int **p;//Declaration of a pointer variable
int i = 0, j;
int rows = 20;
int columns = 30;
p = (int**)malloc(20 * sizeof(int)); //First "bookend" allocates space
printf("Hello World! I have created a dynamic 20-array of 20x30 integers!\n");
if (p == NULL)
{
printf("Failed to allocated memory!");
exit(1);
}
for (i = 0; i < 20; i++)
{
if (p[i] == NULL)
{
printf("Integers not allocated! ");
}
p[i] = (int**)malloc(20 * sizeof(int));
}
for (i = 0; i < 20; i++)
{
for (j = 0; j < 20; j++)
{
if (p[j] == NULL)
{
printf("Integers not allocated! ");
}
p[i][j] = (int *)malloc(40 * sizeof(int));
}
printf("%d\n", p[(i+1)+j]);
}
free(p);
return 0;
}
I hope I got your question right...
What you are getting isn't exactly garbase... When doing p[i][j] = (int *)malloc(40 * sizeof(int)); you are just allocating one more array with 40 elements and putting it's address in p[i][j]... So when you try to print p[(i+1)+j] you are printing the address of that 40 elements array you malloc'd.
There are several issues with your code:
For the initial allocation, each element is an int *, so you need 20 * sizeof(int *), not 20 * sizeof(int).
Any space allocated by malloc is uninitialized, so attempting to read it is undefined behavior. If on the other hand you use calloc, that initializes the allocated memory to all 0.
You go through an extra set of loops attempting to allocate another array to each int location. If you were trying to create a 3D array (and defined p as int ***) that would work, but not for a 2D array.
Don't cast the return value of malloc, as that can mask subtle bugs.
If you want to dynamically allocate a 20 X 30 array of int, you do it like this:
// first allocate 20 int*
int **p = malloc(20 * sizeof(int *));
if (p == NULL) {
perror("malloc failed");
exit(1);
}
int i;
for (i=0;i<30;i++) {
// for each row, allocate 30 int
p[i] = malloc(30 * sizeof(int));
if (p[i] == NULL) {
perror("malloc failed");
exit(1);
}
}
Note that this doesn't set any values in the 2D array, it just allocates the memory for it.
I've noticed that I lack of knowledge of dynamic 2D arrays, after reading some topics here and around the web I've tried something but it seem not to behave correctly:
I want to allocate a 3X3 array of integers, input values in to it and display them, the problem is that always after I enter a value at the index of [3][1] the program crashes... it is weird because I think that I've done everything correctly.
I would also like to hear your thoughts about checking for memory allocation failure,(!(array)) good enough method? I've also seen some examples of deallocating memory up to the failure point, if one occurred.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, //loop control
**array, //pointer to hold the 2D array
N = 3; //rows and columns quantity
array = malloc (N * sizeof (int*)); //allocating rows
if (!(array)) //checking for allocation failure
{
printf("memory allocation failed!\n");
goto exit;
}
else
{
array [i] = calloc (N, sizeof (int)); //allocating columns
if (!(array[i])) //checking for allocation failure
{
printf("memory allocation failed!\n");
goto exit;
}
}
for (i = 0; i < N; i++) //getting user input
{
for (j = 0; j < N; j++)
{
printf("Enter value [%d][%d]:", i+1, j+1);
scanf ("%d", &array [i][j]);
}
}
for (i = 0; i < N; i++) //displaying the matrix
{
printf("\n");
for (j = 0; j < N; j++)
{
printf (" %d", array [i][j]);
}
}
exit:
return 0;
}
You have couple of problems.
You are using uninitialized i.
You haven't allocated memory for all the rows. The following line can allocate memory for only one row.
array [i] = calloc (N, sizeof (int)); //allocating columns
What you need:
Instead of
array [i] = calloc (N, sizeof (int)); //allocating columns
if (!(array[i])) //checking for allocation failure
{
printf("memory allocation failed!\n");
goto exit;
}
Use
for ( i = 0; i < N; ++i )
{
array [i] = calloc (N, sizeof (int)); //allocating columns
if (!(array[i])) //checking for allocation failure
{
printf("memory allocation failed!\n");
goto exit;
}
}
You got lucky it didn't crash earlier. You only allocated one row of the 3x3 matrix:
array [i] = calloc (N, sizeof (int)); //allocating columns
if (!(array[i])) //checking for allocation failure
{
printf("memory allocation failed!\n");
goto exit;
}
You need to do this for each row of the matrix, not just once.
Furthermore, when you call calloc, the value of i is undefined. Wrapping the above block in a foor loop should fix your issue:
else
{
for (i = 0; i < N; i++) {
array [i] = calloc (N, sizeof (int)); //allocating columns
if (!(array[i])) //checking for allocation failure
{
printf("memory allocation failed!\n");
goto exit;
}
}
}
row = n + 1;
col = n + 1;
//used n+1 and i=-1 to avoid segmentation faults
board = malloc(row*sizeof(char *));
for(i=-1;i<row;i++)
{
board[i] = malloc(col*sizeof(char));
if(board[i] == NULL)
{
printf("Out of memory");
exit(EXIT_FAILURE);
}
}
for(i=-1; i < n+1; ++i)
{
free(board [i]);
}
free(board);
When I try to free this array in run time, my compiler goes berserk, please explain, thank you.
arrays cannot have negative index in C.
at the line: for(i = -1; i < row; i++)
I am very sure, there is an off by one error here, where free is freeing one extra block that was not malloc()ed at the end, and you must be getting a segfault error.
malloc returns void pointer, you must cast it. Also minimum index is zero in C.
board = (char**)malloc(row*sizeof(char *));
for(i=0;i<row;i++)
{
board[i] = (char*)malloc(col*sizeof(char));
if(board[i] == NULL)
{
printf("Out of memory");
exit(EXIT_FAILURE);
}
}