Allocating memory and freeing correctly? - c

This is the code for allocating memory for 2 Arrays of uknown size. N is given by the user:
K=malloc(N*sizeof(int));
if(K==NULL){
// printf("Sorry, cannot allocate memory\n");
return -1;
}
for(i = 0;i < N;i++){
C = malloc(N * sizeof(int *));
if (C == NULL){
return -1;
}
for (i = 0 ; i < N ; i++) {
*(C+i) = malloc(K[i] * sizeof(int));
if (*(C+i) == NULL){
return -1; }
}
}
Both arrays are filled with numbers given by the user.
And to free them:
for (i=0 ; i < N ; i++){
for (i=0 ; i < N ; i++){
free(*(C+i));
}
free(C);
}
void free(void*K);
by debugging with gbd i come across this error
Program received signal SIGSEGV, Segmentation fault.
_int_free (av=0x10102464c457f, p=0x8005770, have_lock=) at malloc.c:4304
4304 malloc.c: No such file or directory.
by using valgrind to go deeper into this error it seems, that i have no leaks.What could be the problem?

for(i = 0;i < N;i++){int *));
if (C == NULL){
return -1;
}
with every iteration the previous allocated memory is lost as the pointer is assigned with the reference to the newly allocated memory block.
if your intention was to change the size of the allocated memory you should use realloc instead
Assuming C is int ** (as per you program logic)
C = NULL;
for(i = 0;i < N;i++){
void *tmp = realloc(C, N * sizeof(*C));
if (tmp == NULL){
free(C);
return -1;
}
C = tmp;
}

Related

A realloc noob usage, working for some cases otherwise a seg fault

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

dynamic memory allocation (C Programming)

I am learning about dynamic memory allocation and having a problem while doing the exercise.
I would like to allocate the memory for p. The following is the codes.
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = (int *)malloc(7 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
p++;
*p = i;
printf("%3d",*p);
}
printf("\n");
p = p - 6;
free(p);
p = NULL;
return 0;
}
The running result is:0 1 2 3 4 5
However, when I change the code
p = (int *)malloc(7 * sizeof(int));
to this
p = (int *)malloc(6 * sizeof(int));
the running result would be
0 1 2 3 4 5
Error in `./memo2': free(): invalid next size (fast): 0x0000000001bc5010 ***
Aborted (core dumped)
I think for this code, p only need the memory of the size of 6 integers, could anyone give a explanation?
Another question is that why should p++ be ahead of *p = i? If I make *p = i before p++, the running result would be 0 0 0 0 0 0.
First question - you get an error when you malloc memory for 6 integers because in your for loop you increment the pointer before assigning a value. Therefore you leave the first address you allocated empty. If you assign a value and then increment the pointer this will solve your problem.
Second question - if you perform the printf after incrementing the pointer you won't print the value you just set. You need to assign the value, print it, then increment the pointer.
Here's your code with those changes:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = (int *)malloc(6 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p);
p++;
}
printf("\n");
p = p - 6;
free(p);
p = NULL;
return 0;
}
However, I would recommend you use array indexing syntax. As well as being easier to read, this means that you don't actually change the p meaning that when you free the memory it will be on the correct address. Here's an updated version of your code using array indexing:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = (int *)malloc(6 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
p[i] = i;
printf("%3d",p[i]);
}
printf("\n");
free(p);
p = NULL;
return 0;
}
Your code needs 7 "slots" to store 6 numbers because the very first slot is immediately skipped:
for(i=0; i<6; i++)
{
p++; // <-- Skip to next "slot"
*p = i;
printf("%3d",*p);
}
So the first slot is never used since it's immediately skipped. To fix this, first work with the current pointer, then increment it:
p = malloc(6 * sizeof(int));
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p);
p++; // <-- Skip to next "slot"
}
Also, the pointer you pass to free must be exactly the same pointer you got from malloc. You can calculate the original value by undoing the additions you did in a loop, but it's easier to store the original value (less chance to screw up):
int *p, *orig_p, i;
orig_p = malloc(6 * sizeof(int));
if (orig_p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
p = orig_p;
...
free(orig_p);
For your subquestion2, find the answer in below
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p); //Fix1
p++; //Fix2
}
ie,you should print the value *p before increment the pointer p.
1) When you do like this
for(i=0; i<6; i++)
{
p++; // here before assigning the value you are incrementing address of p(first location is waste)
*p = i;
printf("%3d",*p);
}
So it does not store value in first memory location(this location is wasted). it stores value from second location on wards. so it requires 7 location for 6 numbers.
2) If you make *p = i before p++, like below code-
for(i=0; i<6; i++)
{
*p = i; // you are assigning the value.
p++; // here you are incrementing the value
printf("%3d",*p); // it will print the value at the incremented loaction
}
For example- Consider starting address is 1000. when you do *p = i; i is assigned to 1000, p++; will increment the location to 1004. After incrementing the address you are printing the value. It may give you 0 or garbage values. because printf("%3d",*p); will print the value at 1004. you don't know what value is there. So avoid this types of method.
Try the following code-
p = (int *)malloc(6 * sizeof(int)); // Fix 1
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<6; i++)
{
*p = i;
printf("%3d",*p);
p++; // Fix 2
}
printf("\n");
p = p - 6;
free(p);
p = NULL;
Try this.
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *p, i;
p = malloc(7 * sizeof(int)); /* Memory allocated for 7 intergers */
if (p == NULL)
{
printf("Memory Allocation Errors\n");
exit(1);
}
for(i=0; i<=6; i++) /* Assign values */
{
// This is a better way of assignment, easy to understand
// *(p+i) = i OR p[i] = i
p[i] = i;
printf("%3d",p[i]);
}
printf("\n");
// p = p - 6; /* Not required */
free(p); /* Free the pointer */
// p = NULL; /* Not required */
return 0;
}
The output will be:
0 1 2 3 4 5 6
You have p, that's one slot. Then you increment p six times, that's six more slots. So you need seven slots in total.

Please help me free this dynamically allocated array

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);
}
}

Realloc error in C

I've just started C read the man page but could not find the proper answer. So the code is below
void *p = malloc(10*sizeof(int));
int *q = p;
int NUMOFINT = 10;
for (int i = 0; i < NUMOFINT; i++){
printf("%i ", q[i]);
}
void *realloc(void *p, 20*sizeof(int));
for (int i = 0; i < 21; i++){
printf("%i ", q[i]);
and it is giving this error:
malloc.c: In function ‘main’:
malloc.c:31:24: error: expected declaration specifiers or ‘...’ before numeric constant
I did not quite understand that the size format was ok for malloc() but not ok for realloc. So how do I correct the error?
Edit:
so when I make it as:
void *morep = realloc(p, 20*sizeof(int));
int *q2 = morep;
for (int i = 0; i < 20; i++){
printf("%i ", q2[i]);
}
it prints out q2[11] as 135121
This
void *realloc(void *p, 20*sizeof(int));
is wrong. You want
p = realloc(p, 20*sizeof(int));
Incidentally, this line is also a problem (but will compile fine):
for (int i = 0; i < 21; i++){
You allocated p to 20*sizeof(int) bytes, so element 20 is past the end of the array. You want:
for (int i = 0; i < 20; i++){
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int *temp; /* To use with realloc, it's more secure */
void *p = malloc(10*sizeof(int));
int *q = p;
int NUMOFINT = 10;
/* dont forget to compile with -std=99 flag, if you use this kind of for loop */
for (int i = 0; i < NUMOFINT; i++){
printf("%i ", q[i]);
}
printf("\n");
/* It's more secure to use this kind of realloc */
temp = realloc (p, 20 * sizeof(int) );
if (temp == NULL)
{
fprintf(stderr,"Reallocation failed --> %s\n", strerror(errno));
free(p);
exit(EXIT_FAILURE);
}
else
{
p = temp;
}
/* Zeroing after realloc */
for (int i = NUMOFINT; i < 21; i++)
q[i] = 0;
for (int i = 0; i < 21; i++)
{
printf("%i ", q[i]);
}
printf("\n");
return 0;
}
realloc can tries to expand the existing memory block in heap, if its not possible it will allocate a new separate block of memory for the new size and it will copy the data from old memory block to the new memory block also.
So if realloc returns the address same as p then it just expands the old memory block. Or else we have to free the old memory block and start using the new memory block returned by realloc.
#define NUMOFINT 10
#define NUMOFINT_NEW 20
void *p = malloc(NUMOFINT * sizeof(int));
int *q = p;
void *temp = NULL;
for (int i = 0; i < NUMOFINT; i++)
{
printf("%i ", q[i]);
}
temp = realloc(p, NUMOFINT_NEW * sizeof(int));
if (temp == NULL)
{
exit(0);
}
else if (temp != p)
{
free(p);
p = temp;
}
//else temp is equal to p
for (int i = 0; i < NUMOFINT_NEW; i++)
{
printf("%i ", q[i]);
}
Here q[0] to q[9] will have the values(0, 1, 2..9) assigned, and the rest (q[10] to q[19]) will have garbage value. We have not memset the newly allocated memory to 0 also.
you can memset also before for loop,
memset((q + NUMOFINT), 0, (NUMOFINT_NEW - NUMOFINT));
Mistakes in your program are
1) compilation error because
void *realloc(void *p, 20*sizeof(int)); This statement doesn;t looks like a function call.
2) for (int i = 0; i < 21; i++) - After memory is realloced to 20 elements, you can access only upto 19th, accessing 20th may leads to crash(undefined behaviour).
3) it prints out q2[11] as 135121 - Newly reallocated memory is neither memset to 0 nor assigned any meaningful values.

C Programming- Malloc/Free

So I have a code and when I run it, it hangs when I enter a size greater than 3. When it's exactly 3 it runs smoothly. I narrowed down the problem to malloc and free and I don't know what the problem is. I'm new at this so any help is appreciated.
do //repeatedly ask the user to put a number between 3-9
{
printf("Enter the size of the game board between 3-9: ");
scanf("%d", &size);
}while(size<3 || size>9);
if((board = (char***)malloc(sizeof(char**)*size))==NULL)
printf("Memory Allocation failed\n");
for(i=0; i<size; i++)
{
if((board[i] = (char**)malloc(sizeof(char*)*size))==NULL)
printf("Memory Allocation failed\n");
for(j=0; j<size; j++)
{
if((board[i][j] = (char *)malloc(sizeof(char)*4))==NULL)
printf("Memory Allocation failed\n");
strcpy(board[i][j], "Go");
}
}
/*************Some random code ***********/
free(board);
for(i=0;i<size;i++)
{
free(board[i]);
for(j=0;j<size;j++)
free(board[i][j]);
}
The problem is you access board after you freed it. You should release memory in exactly the reverse order that you malloc it.
An alternative approach is that you can allocate all the memory you need in a whole, like
char ***board = NULL;
char **rows = NULL;
char *data = NULL;
if((board = (char***)malloc(sizeof(char**)*size))==NULL)
printf("Memory Allocation failed\n");
if((rows = (char**)malloc(sizeof(char*)*size*size))==NULL)
printf("Memory Allocation failed\n");
if((data = (char *)malloc(sizeof(char)*size*size*4))==NULL)
printf("Memory Allocation failed\n");
for (i = 0; i < size; i++) {
int board_offset = i * size;
board[i] = rows[board_offset];
for (j = 0; j < size; j++) {
int row_offset = board_offset + j;
rows[row_offset] = data[row_offset * 4];
stcpy(data[row_offset * 4], "GO");
}
}
free(board);
free(rows);
free(data);

Resources