Free() inside a while loop - c

I'm trying to run this program where a character array is created and allocated memory dynamically. Later the array elements are populated with the string "hello" for 10 consecutive locations. The values are assigned to the string elements using strdup() function call.
Once all the elements are assigned the elements are freed up in the while loop.When I run the program in the Visual Studio, the program crashes after the last pointer to the char array is freed. I believe the termination condition for the while loop is correct. But I'm not able to identify what exactly is causing the issue.
Code:
char **p;
int i;
p = malloc(10 * sizeof(char *));
for (i = 0; i < 10; i++) {
p[i] = strdup(“hello”);
}
while (*p) {
free(*p++);
}

If you want very much to use your while loop then you should write the code the following way
char **p;
int i;
p = malloc(11 * sizeof(char *));
for (i = 0; i < 10; i++) {
p[i] = strdup(“hello”);
}
p[i] = NULL;
while (*p) {
free(*p++);
}
Take into account that you need also to free the initial value of p itself. So the correct code with the while loop could look like
char **p;
int i;
p = malloc(11 * sizeof(char *));
for (i = 0; i < 10; i++) {
p[i] = strdup(“hello”);
}
p[i] = NULL;
char **q = p;
while (*q) {
free(*q++);
}
free( p );

Accessing values outside of array bound, means un authorized memory access. So only,You got crashes at end because of p++ . So try like this.
i=0;
while(i<10)
{
free(p[i]);
i++;
}

You should be iterating over ten elements, not until the non-existent sentinel value (NULL):
for (i = 0; i < 10; i++) {
free(p[i]);
}
Your current code dereferences p[10], which is outside the array bounds and therefore triggers undefined behaviour.

Related

My program crashes when using realloc in C

#include <stdio.h>
#include <stdlib.h>
char **Names;
int size = 2; //Minimum size for 2D array
void main() {
int i;
Names = (char **)malloc(size * sizeof(char *)); // First initaliaion of 2D array in heap
for (i = 0; i < size; i++)
Names[i] = (char *)malloc(20 * sizeof(char));
printf("\nenter");
for (i = 0; i < size; i++)
scanf("%s", Names[i]);
while (1) {
size++;
Names = (char **)realloc(Names, size * sizeof(char *)); //Dynamic allocation of 2D aray
for (i = 0; i < size; i++)
Names[i] = (char *)realloc(Names[i], 20 * sizeof(char));
i = size - 1;
printf("\nenter");
scanf("%s", Names[i]);
for (i = 0; i < size; i++)
printf("\n%s", Names[i]);
}
}
It doesn't crash immediately it depends on the "size" I initialized.
It crashes after 5 allocations for me.
I tried adding free function but it did not seem to help.
After this memory reallocation
size ++;
Names= (char**)realloc(Names,size*sizeof(char *));
the last pointer pf the array of pointers has an indeterminate value because it was not initialized.
As a result the call of realloc for the last pointer in this loop
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
invokes undefined behavior.
Before executing the loop you need to initialize the last pointer at least like
Names[size-1] = NULL;
In fact there is no sense to use the for loop because what you need is to allocate memory for the newly added pointer. The allocated memory pointed to by the early created pointers is not being changed in size.
So instead of
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
you could just write
Names[size-1] = malloc( 20 * sizeof( char ) );
Pay attention to as you have an infinite loop then the memory reallocation sooner or later can fail.
Also according to the C Standard the function main without parameters shall be declared like
int main( void )

C: adding elements to an array

I'm trying to test a program that creates an array with 0 elements in it, then adds elements to it (reallocating memory each time), and then printing out the elements. But, I keep getting errors when I try to run it.
int main(int argc, const char * argv[]) {
int num = 0;
int n = 10;
int **array = malloc(0);
for (int i = 0; i < n; ++i)
{
++num;
array = realloc(array, num * sizeof(int*));
array[num-1] = &i;
}
for (int j = 0; j < n; ++j)
{
printf("%d", &array[j]); // error 1
}
return 0;
}
I'm sorry I didn't include the errors with the original post. I think I fixed one of them. Here is the other:
Error 1: Format specifies type 'int' but the argument has type 'int *'
This answer is based on the assumption that you are printing a simple array, since you don't show what output you expect. You are using one more step of indirection than you need, and too many variables. Take note that indexing is different from length (often by 1).
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, n = 10;
int *array = NULL; // no need for double star, or fake allocation
for (i = 0; i < n; ++i)
{
array = realloc(array, (i + 1) * sizeof(int)); // remove the *, add 1 for num elements
array[i] = i;
}
for (i = 0; i < n; ++i)
{
printf("%d", array[i]); // remove the &
}
free(array); // don't forget this
return 0;
}
Program output:
0123456789
In practice, you should assign the result of realloc to another pointer variable, check it's ok, and then replace the original pointer var.
printf("%d", &array[j]); // error 1
The & is the address operator. So it is making something a pointer. Your array is already an array of pointers to integer.
By using the & you are trying to print the address of the integer pointer itself.
Try using * instead of &. * means that you want to print the value of the integer pointer.
printf("%d", *array[j]); // error 1

Two dimensional array malloc in C ---> error?

I am trying to make two dimensional array function, but somehow it is not working. The code here:
#include <stdio.h>
#include <stdlib.h>
int **multiTable (unsigned int xs, unsigned in ys)
{
unsigned int i, j;
int **table = int(**)malloc(xs * ys * sizeof(int*));
for(i = 0; i < ys; i++)
{
for(j = 0; j < xs; j++)
{
table[i][j] = j * i;
}
}
free(**table);
return table;
}
So first of all, should I also add inside the malloc the row (xs)? Or should it work, if I work only with the columns? --> like this:
int **table = int(**)malloc(ys * sizeof(int*));
That is not going to work as an array of pointers int **table is not contiguous and it is not equivalent to a 2d array table[a][b].
You can however use a pointer to an array if you want to use a single malloc.
int (*table)[xs] = malloc( ys * sizeof(*table));
for( int i = 0; i < ys; i++)
{
for( int j = 0; j < xs; j++)
{
table[i][j] = i;
}
}
free( table ) ;
And do not return table after you free it as your return call does.
It seems you mean the following
int ** multiTable( unsigned int xs, unsigned int ys )
{
unsigned int i, j;
int **table = malloc( ys * sizeof( int * ) );
for ( i = 0; i < ys; i++ )
{
table[i] = malloc( xs * sizeof( int ) );
for ( j = 0; j < xs; j++ )
{
table[i][j] = j * i;
}
}
return table;
}
'table' is a 2-D pointer. First understand what is a 2D pointer. A pointer is a special type of variable that is used to store the address of another variable. So a 2D pointer is a special variable that is again used to store the address of a pointer variable.
Now imagine that you have a single array of pointers(collection of base address of different 1-D array), that will store the base address of many 1-D arrays.
To dynamically allocate memory to this array of pointers you need the statement
table=(int**)malloc(sizeof(int*)*xs);
Now you have an array with 'xs' number of elements, and you can access each element by table[0], table[1], table[2]..and so on..., but none of these arrays is allocated memory. So you need to allocate memory to each of the array individually using a loop like this:
for(i=0;i<xs;i++)
table[i]=(int*)malloc(sizeof(int)*ys);
So your over-all program becomes:
int **table; // table is a 2D pointer
table=(int**)malloc(sizeof(int*)*xs);
for(i=0;i<xs;i++)
table[i]=(int*)malloc(sizeof(int)*ys);
for(i = 0; i < ys; i++)
{
for(j = 0; j < xs; j++)
{
table[i][j] = j * i;
}
}
return table;
You don't need to free the array before returning it. Doing so will make your pointer 'table' a dangling pointer that is still referring to a memory that is no longer allocated, so just return 'table' without the statement:
free(table);
The above statement will lead to a dangling memory that has no access point, ans so is useless. This is a memory leakage problem that arises when memory gets accumulated, and this memory is no more accessible through your program and could not be relocated for other purpose, such a memory is called dangling memory.

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.

whats going wrong with my program?

the program is supposed to compare the strings and place them in alphabetical order, but the final printf statement prints garbage...where am i going wrong here?
i have used an array of pointers to strings and declared them in the begining, i have even tried using temp as an array rather than pointer stil doesnt quite work
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int j;
int i;
char *temp;
char *string[5] = {"ibrahim","laura","peter","degea"};
for ( i = 0; i< 4;i++)
printf("%s\n", string[i]); //allocating memory
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
for ( i=0; i< 3; i++)
for(j =i+1; j<4; j++)
{
if(strcmp(string[i], string[j]) > 0)
{
strcpy(temp, string[i]);
strcpy(string[i], string[j]);
strcpy(string[j], temp);
}
}
for (i = 0; i< 4; i++)
{
printf("%s\n",string[i]);
puts("\n");
}
free(string);
free(temp);
return 0;
}
string[i] = (char*)malloc (30 * sizeof(char));
This is overwriting the existing initialized values.
EDIT
for( i = 0; i< 10 ;i++)
temp = (char*)malloc(30*sizeof(char));
WHAT? you are allocating memory over and over 10 times on a single pointer?
EDIT 2:
The original post is lost (read Edited). By the time you are reading this answer, both Mr. Jonathan Leffler and this poster migh look like absolute fools in this world.
The code originally destroyed its data array (by allocating new pointers). Now it seems to throw memory away by allocating temp four times (but Jeevan's edit reinstates the old code in indented form). The old code allocated space for strings but never initialized them (having thrown away the value that was in the array beforehand).
NB: any commentary on the code could easily be invalid by the time you're reading the commentary — the code in the question could have changed.
for (i = 0; i < 10; i++)
string[i] = malloc(30);
This code tramples out of the bounds of the string array (dimension is 5). It also loses the data originally in the array.
You need to use strcmp() to compare the strings, but you simply need to swap pointers rather than using strcpy() at all.
The comment // allocating memory beside a printf() statement is misleading, too.
This stands a chance of working. Note that there is no memory allocation:
#include <stdio.h>
#include <string.h>
int main(void)
{
int j;
int i;
char *string[] = { "ibrahim", "laura", "peter", "degea" };
for (i = 0; i < 4; i++)
printf("%s\n", string[i]);
for (i = 0; i < 3; i++)
{
for (j = i+1; j < 4; j++)
{
if (strcmp(string[i], string[j]) > 0)
{
char *temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
for (i = 0; i < 4; i++)
printf("%s\n",string[i]);
return 0;
}
Output:
ibrahim
laura
peter
degea
degea
ibrahim
laura
peter
Comment: don't try sorting thousands of strings using this sort algorithm.
You are overwriting the existing string array contents with malloc, that too 10 times.
Please use braces in your code for better understanding
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
can be written as
for( i = 0; i< 10 ;i++) // why to allocate memory ten times, that too overwriting
{
string[i] = (char*)malloc (30 * sizeof(char));
}
temp = (char*)malloc(30*sizeof(char));
when you declare :
char *string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
the pointer *string[0] to *string[3] allocated to a address in the memory, where will stored the init values "ibrahim","laura"...
when you use malloc function for the pointer string[i] = (char*)malloc (30 * sizeof(char));
the pointer *string[0] to *string[4] will be allocated to another address in the memory. so the value at these address are different from that you initialized (ibrahim,laura).
you should use static array instead dynamic as below
char temp;
char string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
remove all the malloc, free function.

Resources