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;
}
}
}
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
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;
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.
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);
}
}
I am using realloc to allocated memory at runtime in dynamic array. Firstly, I allocated a memory with calloc with sizeof a random integer a. In my program, I have taken a=2. After that I want to store some 14 random values generated, so I have to resize the memory using realloc. I am doing the same in a for loop. FOr 1 iteration, realloc works but after that size doesnt increase and a error occurs "corruption in heap". I am not able to understand the problem. Pls help me if you can, in understanding where the problem is occuring and how to solve it.
Thanks a lot.
Below is my code:
j=j*a; //a=3
numbers = (int*) calloc(b, j); //b=14, no of elements I want to store
printf("Address:%p\n",numbers);
if (numbers == NULL)
{
printf("No Memory Allocated\n");
}
else
{
printf("Initial array size: %d elements\n", a);
printf("Adding %d elements\n", b);
}
srand( (unsigned) time( NULL ) );
for(count = 1; count <= b ; count++)
{
if(i <= j)
{
numbers[count] = rand() % 100 + 1;
printf( "Adding Value:%3d Address%p\n", numbers[count],numbers[count] );
i++;
}
if (i > j)
{
printf("Increasing array size from %d bytes to %d bytes\n",j,j*a);
j=j*a;
numbers = (int*) realloc(numbers,j);
printf("Address:%p\n",numbers);
if(numbers == NULL)
{
printf("No Memory allocated\n");
}
}
}
free(numbers);
return 0;
}
The initial array length (length and size are not the same) is b, not a.
Adding b elements? I don't think you are.
Arrays are zero-based in C. You loop should be for(count=0; count<b ; count++).
count is a terrible name for a loop variable. count should hold the number of elements and not be a loop variable.
It's hard to imagine what j could be. Since you use it as the element size in your call to calloc it ought be at least be a multiple of 4, the size of in int. What is it?!
The realloc doesn't seem to bear any relation to the calloc.
I'm sure there are lots of other problems. If you want more help then a clear statement of what your goal is would be required.
EDIT
It sounds like you want something like this:
int capacity = 10;
int count = 40;
int i;
int* array = (int*)malloc(capacity*sizeof(int));
for (i=0; i<count; i++)
{
if (i==capacity)
{
capacity *= 2;
array = (int*)realloc(array, capacity*sizeof(int));
}
array[i] = RandomIntInRange(1, 100);
}
free(array);
Notes:
No error checking. In production code you would check that the allocations succeeded, and the realloc done this way would leak if it failed. But there's no point confusing the message with error checking when you are still at this level of understanding.
No reading input - you can do that.
No writing output - you can do that.
The integer "j" is not initialized in your code, resulting in a = 0 * 3, meaning a will be zero and no memory will be allocated. The segfault is due to you not handling that numbers is NULL. Change to and set j to something meaningful
#include <stdlib.h>
#include <stdio.h>
void
main (int argc, char *argv[])
{
int a = 3;
int j = 1 * a; //a=3
int b = 14;
int *numbers = calloc (b, j); //b=14, no of elements I want to store
int count = 0, i = 0;
printf ("Address:%p\n", numbers);
if (numbers == NULL)
{
printf ("No Memory Allocated\n");
return;
}
else
{
printf ("Initial array size: %d elements\n", a);
printf ("Adding %d elements\n", b);
}
srand ((unsigned) time (NULL));
for (count = 1; count <= b; count++)
{
if (i <= j)
{
numbers[count] = rand () % 100 + 1;
printf ("Adding Value:%3d Address%p\n", numbers[count],
&(numbers[count]));
i++;
}
if (i > j)
{
printf ("Increasing array size from %d bytes to %d bytes\n", j,
j * a);
j = j * a;
numbers = (int *) realloc (numbers, j);
printf ("Address:%p\n", numbers);
if (numbers == NULL)
{
printf ("No Memory allocated\n");
}
}
}
free (numbers);
}