ansi c struct {with dynamic array} assigned to array which is realloc - c

why the below code gives me error of "double free or corruption"... when i compile and run with gcc [(Debian 4.4.4-8) 4.4.5 20100728 (prerelease)]. Thanks in advance!
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *index1;
} data;
void doo(int *);
int main(int argc, char *argv[])
{
int *a = (int *) malloc(10*sizeof(int));
int i;
for(i=0; i<10; i++)
{
a[i] = 2*i;
}
doo(a);
data one;
one.index1 = a;
printf("%d\n", one.index1[4]);
free(a);
printf("%d\n", one.index1[4]);
free(one.index1);
return 0;
}
void doo(int *b)
{
b = (int *) realloc(b, 5*sizeof(int));
return;
}

one.index1=a;
...
free(a);
...
free(one.index1);
...
Ergo, the double free.
void doo(int *b)
{
b = (int *) realloc(b, 5*sizeof(int));
return;
}
When you pass the a pointer to this function, its value(which is infact an address), gets copied into b, another local int pointer.
Now, when you realloc space for 5 ints, it changes the space allocation for a infact. So your space gets reduced from 10 to 5 ints.
As requested by OP, to get the same data & separate memory pointers, space must be allocated afresh for the new pointer, as a pointer is after all, just a variable, holding an address. If you allocate two separate blocks, you would get two separate addresses, which can be freed individually.

Because the storage pointed to by 'a' and 'one.index1' are the same (assignment before the first printf). Thus you have a double free.

You are passing to doo a pointer. You modify the pointer itself, but your main function does not get the new address.

That happens because you make one.index1 and a point to the same memory location.
To test this add the following to your code:
one.index1 = a; // from now on, both variables point to the same address
printf("-> 0x%x\n", one.index1);
printf("-> 0x%x\n", a);
printf("%d\n", one.index1[4]);
free(a); // release the resource pointed by a
// You should not try to print the data of one.index1[4] since
// that piece of memory doesn't exist no more.
printf("%d\n", one.index1[4]);
free(one.index1); // Problem: trying to free the same memory resource TWICE.
You'll notice that both pointers will print the same memory addresses. So after free(a); is executed, performing free(one.index1); is redundant, and trying to free a resource that is not allocated anymore is what is causes the problem.

Related

Question about pointer to array used in malloc/free

I saw the following code:
#include <stdlib.h>
void foo(char n)
{
int (*vals)[n] = malloc(sizeof(int[n]));
for (int i = 0; i < n; ++i)
(*vals)[i] = i;
free(vals);
}
int main(int argc, char **argv)
{
foo(*(argv[1]));
return 0;
}
This lines makes me very uncomfortable:
free(vals);
vals is a pointer pointing to an array. This looks right, but I just have a difficult time internalizing it, I do not know why.
I am more used to the following style:
int *p = (int*)malloc(n * sizeof(int));
......
free(p);
In this code, p is a pointer pointing to the start of a memory region for some integers, the malloc and free are symmetric in that they both work on a pointer type; yet the original code has malloc() working on a pointer to an array and free() a pointer.
Out of curiosity, I modified the original code:
free(vals); ==> free(*vals);
I was expecting this change will fail at compiler, the reason is *vals is an array now. But gcc is fine and valgrind does not complain memory leak.
I know C has a thing called array degenerates to pointer at function call. But I just cannot internalize this stuff. Sorry writing so long to describe a problem, wish you could see my struggle. Is there a definitive doc/stackoverflow/blog to clear this up - best C99 or later?
Thanks!
writing free(*vals); is same as writing free(vals);
edited your code to clear that a little bit
#include <stdlib.h>
#include <stdio.h>
void foo(char n)
{
int (*vals)[n] = malloc(sizeof(int[n]));
for (int i = 0; i < n; ++i)
(*vals)[i] = i;
printf("*val is %p\n", *vals);
printf("val is %p\n", vals);
printf("&val is %p\n", &vals);
free(vals);
}
int main()
{
foo(10);
return 0;
}
and this is the output:
*val is 0000018190365d50
val is 0000018190365d50
&val is 0000005d9dbff7b8
note that vals is Array pointer which means that its base type is an array of n integers where the pointer val is created in that stack and points to the whole array, not the first element only and that array is created in the heap, to illustrate, look at the following graph:
so for example if you write:
printf("val is %p\n", vals);
printf("val+1 is %p\n", vals+1);
the output will be :
val is 00000207ef0c5d50
val+1 is 00000207ef0c5d78
note the difference between the 2 is about 40 bytes as val points to the whole array not only one element as in case of int *p = (int*)malloc(n * sizeof(int));
note that when I say it points to the whole array, I also mean it points to the base address of the array.
in case of *Vals, look at the next graph:
*Vals is just an address of the first element of the array which is by the way is same as the base address of the array.
refer to free() manual, they said:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc() or
realloc(). Otherwise, or if free(ptr) has already been called before,
undefined behavior occurs. If ptr is NULL, no operation is performed.
and what does malloc() function return ?
it returns the base address of your reserved space in heap, so writing free(vals); is same as writing free(vals);
This codes uses dynamic VLA.
I think that it may be easier to understand if the code is reformulated with a typedef.
void foo(char n)
{
typedef int T[n];
T *vals = malloc(sizeof(T));
...
free(vals);
}
Now it looks like a tivial use of a single dynamic object.
To access elements of an array first the pointer has to be dereferenced *vals forming an array, which decays to int* pointer suitable for [] operator.

Releasing pointer memory aswell as pointer itself

A "Deeltal" keeps track of how many dividers an integer has (count) and keeps them in an array (dividers).
Examples:
value = 8 -> count = 3 and dividers = {1,2,4}
value = 10, count = 3, dividers = {1,2,5}
Hope everything is clear, take a look at the following code:
typedef struct{
int value;
int count;
int* dividers;
} Deeltal;
void free_dividers(Deeltal *g){ /*Deletes the int* dividers of a given Deeltal*/
free (g - > dividers);
}
/* the following two functions have the same purpose: deleting the content of a
given amount of "Deeltal" AND deleting the pointer to it aswell*/
void free_amountOfdeeltal(Deeltal *d, int amount){
int i;
for (i = 0; i < amount; i++){
free_dividers(&d[i]);
}
free(d);
}
void free_amountOfdeeltalVersion2(Deeltal **g, int amount){
int i;
for(i = 0; i < amount; i++){
free_dividers(&(*g)[i]);
}
free(*g);
}
If my main looked something like this
int main(void){
/*EDIT 3/11/2017: forgot to allocate memory for *d and initializing g.
Thanks for pointing this out*/
Deeltal g = 0;
g.value = 6; g.count = 3; g.dividers = {1,2,3};
Deeltal *d = malloc(sizeof(Deeltal));
d->value = 6; d->count = 3; d->dividers = {1,2,3};
free_amountOfdeeltal(&g);
free_amountOfdeeltalVersion2(&d);
}
What is the difference between free_amountOfdeeltal and free_amountOfdeeltalVersion2?
Both should do the same thing: releasing the memory of a Deeltal and also deleting the pointer pointing to that memory.
On a sidenote:
How do you delete the memory as well as the pointer?
Not withstanding calling this function with invalid data as pointed out by others .. I'll attempt to answer the question I think you are asking.
On a sidenote: How do you delete the memory as well as the pointer?
You can't really "delete the pointer" in this context as a pointer is simply a variable that is assigned an address. You delete memory that was allocated to you by passing free a pointer to the memory. Note that free does not modify the value of the pointer at all. (It can't because the pointer is passed by value.) After the call to free the pointer still points to the same memory address.
If what you mean is "how can I assign a meaningful value to the pointer to identify that its memory has already been deleted," then you can use the second form of your function:
void free_amountOfdeeltalVersion2(Deeltal **g, int amount);
and set *g to NULL before returning. You can then use this information than the pointer is NULL to identify the memory has already been deleted.
You didn't allocate any memory for d so your pointer doesn't point to any structure. Therefor, you can't access its properties or free its memory because you didn't reserve it in the first place. There's no way this code could come remotely close to compiling.
First of all you should be allocating memory for a "Deeltal" structure like this:
Deeltal *d = malloc(sizeof(Deeltal));
I recommend you go back and relearn how pointers work, as you're doing some really weird stuff there.

What happens if you don't free dynamically allocated memory in a function?

I am learning how to write functions in C to accept an array and return a modified array.
In function testfunc (which is supposed to simply add 10 to each element of input array b) I am allocating memory for npts number of integers using malloc. But since I want to return this array using a pointer, I am not freeing this memory at the end of the function. Suppose I call this function 100 times like I am doing in the code, so what happens to the all the memory allocated during the code ? Is the amount of memory used by the code 100*10*4 bytes ? For a function which doesn't work on dynamic memory allocation, I think memory allocated to variables disappears when the function returns the final value and when it is called again, it again allocates memory and so on. But I am confused as to what happens in this case.
i cannot free the allocated memory inside the function since i need it to return the array to the main function, but also i need to call this function more than 100 times for different arrays, so if it keeps on allocating again and again, it will run out of memory
And is there a way to check how much memory a code is using ? (other than looking at Activity Monitor on Mac-OSX).
Thanks !
/* code to test returning array from functions */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int* testfunc(int *a,int npts);
int main(int argc, char* argv[])
{
int *b;
int a[10],i,j,npts=10;
b=(int *) malloc(sizeof(int)*npts);
for (j=0; j <100; j++)
{
printf("iteration number %d \n",j);
for (i=0; i<npts; i++)
{
a[i]=i;
printf("%d \n",a[i]);
}
b=testfunc(a,npts);
printf("returned array \n");
for (i=0; i<npts; i++)
{
printf("%d \n",b[i]);
}
}
printf("the size of one integer is %d \n",sizeof(int));
return 0;
}
int* testfunc(int *b,int npts)
{
int *c;
int i=0;
c=(int *) malloc(sizeof(int)*npts);
for (i=0; i<npts; i++)
{
c[i]=b[i]+10;
}
return c;
}
This is the possible solution to avoid allocating memory inside a function and being able to call the function multiple times
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void testfunc(int *c,int *d,int npts);
int main(int argc, char* argv[])
{
int *a,*b;
int i,j,npts=10;
a=malloc(sizeof(int)*npts);
b=malloc(sizeof(int)*npts);
for (j=0; j <100; j++)
{
printf("iteration number %d \n",j);
for (i=0; i<npts; i++)
{
a[i]=i;
printf("%d \n",a[i]);
}
testfunc(a,b,npts);
printf("returned array \n");
for (i=0; i<npts; i++)
{
printf("%d \n",b[i]);
}
}
printf("the size of one integer is %d \n",sizeof(int));
free(a);
free(b);
return 0;
}
void testfunc(int *c,int *d,int npts)
{
int i=0;
for (i=0; i<npts; i++)
{
d[i]=c[i]+10;
}
}
c=(int *) malloc(sizeof(int)*npts);
:
return c;
This passes back both the memory and the responsibility for managing it.
It has become the responsibility of the caller (main in this cae) to free it when finished.
Where your real problem lies is here in main:
b=(int *) malloc(sizeof(int)*npts);
:
for (some number of iterations)
b=testfunc(a,npts); // overwrites b
On that "overwrites" line, you actually have a memory leak because you lose access to the memory currently allocated for b (both originally and in the prior iteration of the loop).
And, as an aside, please don't cast the return value of malloc in C. It's not needed and can hide certain subtle errors that you really don't want to have to debug :-)
Since you are using malloc, which means you are allocating memory from heap not stack.
You should firstly figure out the mechanism of heap and stack.In C,malloc will help programmer allocate memory from heap, the same as new in C++.
So even if the function return the final value, the memory allocated will not be freed.If you call the function 100 times, it will allocate memory for you 100 times.
And as for a tool, you can refer to Valgrind, which is a powerful tool to check whether there exists a memory error.
It's main that have to free() the allocated space, but you have to be sure that you don't modified the value on the space during the function.
If dynamically allocated memory is not freed, it results in a memory leak and system will run out of memory. This can lead to program crashing.
hey objective of call by reference is to modify the input pointer and return back to caller.
means modified values i.e address still with caller.
You can simply do modification without allocate memory in your function
Just correction in your second approach
void testfunc(int *c,int npts)
{
int i=0;
for (i=0; i<npts; i++)
{
c[i] += 10; //YOU JUST INCREMENT VALUE by 10
}
}
My approach to write function:
no memory allocation
no multiple arguments
keep necessary input, output argument , return value
here int *c, npts -- input argument, output [ your value modified in int *c location]

Cannot return int array

I want to use only studio.h library to convert from decimal number to binary number by using an array to store remainder but the result is not correct, maybe i have problem with memory allocation or return value is wrong, please help me to check it.
Thank you so much!
#include <stdio.h>
int n = 0;
int* DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
void main(){
int *d1 = DecimalToBinary(5);
int *d2 = DecimalToBinary(10);
for(int i = n-1 ;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
for(int i = n-1 ;i>=0;i--)
printf(" %d",d2[i]);
}
You return a pointer to a local array. That local array is on the stack, and when the function returns the array goes out of scope and that stack memory will be reused when you call the next function. This means that the pointer will now point to some other data, and not the original array.
There are two solutions to this:
Declare the array in the function calling DecimalToBinary and pass it as an argument.
Create the array dynamically on the heap (e.g. with malloc) and return that pointer.
The problem with method 2 is that it might create a memory leak if you don't free the returned pointer.
As noted by Craig there is a third solution, to make the array static inside the function. However in this case it brings other and bigger problems than the two solutions I originally listed, and that's why I didn't list it.
There is also another serious problem with the code, as noted by Uchia Itachi, and that is that the array is indexed by a global variable. If the DecimalToBinary function is called with a too big number, or to many times, this global index variable will be to big for the array and will be out of bounds for the array.
Both the problem with dereferencing a pointer to an out-of-scope array and the indexing out of bounds leads to undefined behavior. Undefined behavior will, if you're lucky, just lead to the wrong result being printed. If you're unlucky it will cause the program to crash.
You are returning a pointer to a locally allocated array. It is allocated on the stack, and goes away when the function returns, leaving your pointer pointing to garbage.
You have a few options. You could pass an array in to fill:
void DecimalToBinary(int result[10],int number){
while(number!=0){
result[n++] = number%2;
number/=2;
}
return result;
}
// usage example:
int b[10];
DecimalToBinary(b, 42);
Or you could allocate an array on the heap:
int* DecimalToBinary(int number){
int *a = (int *)malloc(sizeof(int) * 10);
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
// usage example
int *b = DecimalToBinary(42);
free(b); // when finished with it
Or you could wrap the array in a struct:
typedef struct {
int b[10];
} result;
result DecimalToBinary(int number){
result r;
while(number!=0){
r.b[n++] = number%2;
number/=2;
}
return r;
}
// usage example
result r = DecimalToBinary(42);
If you do the malloc() option, do not forget to free() the returned data when you're done with it, otherwise it will hang around. This is called a memory leak. In more complex programs, it can lead to serious issues.
Note: By the way, if your number is larger than 1023 (10 binary digits), you'll overrun the array. You may also wish to explicitly stop once you've stored 10 digits, or pass the size of the array in, or compute the required size first and allocate that much space. Also, you will get some odd results if your number is negative, you might want to use number&1 instead of number%2.
Note 2: As noted elsewhere, you should make n local, or at the very least reinitalize it to 0 each time the function is called, otherwise it will just accumulate and eventually you'll go past the end of the array.
int[10] is not the same as int *; not only is the former created on the stack, it is a different type alltogether. You need to create an actual int * like so:
int *a = malloc (10 * sizeof (int));
Of course, don't forget to free() it after use!
What you can also do and what is commonly done in C is creating the array where it is called and provide a pointer to that array to the function, this way when the array is on the stack of the function that calls it and not in the function self. We also have to specify the size of the array on to that function, since the function cannot know to how many elements the pointer points to
void DecimalToBinary( int number, int* output, unsigned size ) {
/*adapt this to your liking*/
int i;
for ( i = 0; i < size && number != 0; i++) {
output[i] = number%2;
number/2;
}
}
and in you main function you would call it like this:
int array[10];
DecimalToBinary( 5, array, sizeof(array)/sizeof(array[0]));
now array has the same result as a would have had in your example.
The problem in your code lies here..
int * DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
The array a scope is only till this function. Once this function terminates, the memory allocated for this array will be released, either u need to use dynamic memory allocation or make array a global.
This is the correct program:
#include <stdio.h>
int n = 0;
int a[10] = {0};
int* DecimalToBinary(int number){
n = 0;
while(number!=0){
a[n++] = number%2;
number = number/2;
}
return a;
}
int main(){
int *d1;
int *d2;
int i;
d1 = DecimalToBinary(5);
for(i = n-1;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
d2 = DecimalToBinary(10);
for(i = n-1;i>=0;i--)
printf(" %d",d2[i]);
printf("\n");
}

Directly assigning values to C Pointers

I've just started learning C and I've been running some simple programs using MinGW for Windows to understand how pointers work. I tried the following:
#include <stdio.h>
int main(){
int *ptr;
*ptr = 20;
printf("%d", *ptr);
return 0;
}
which compiled properly but when I run the executable it doesn't work - the value isn't printed to the command line, instead I get an error message that says the .exe file has stopped working.
However when I tried storing the value in an int variable and assign *ptr to the memory address of that variable as shown below:
#include <stdio.h>
int main(){
int *ptr;
int q = 50;
ptr = &q;
printf("%d", *ptr);
return 0;
}
it works fine.
My question is, why am I unable to directly set a literal value to the pointer? I've looked at tutorials online for pointers and most of them do it the same way as the second example.
Any help is appreciated.
The problem is that you're not initializing the pointer. You've created a pointer to "anywhere you want"—which could be the address of some other variable, or the middle of your code, or some memory that isn't mapped at all.
You need to create an int variable somewhere in memory for the int * variable to point at.
Your second example does this, but it does other things that aren't relevant here. Here's the simplest thing you need to do:
int main(){
int variable;
int *ptr = &variable;
*ptr = 20;
printf("%d", *ptr);
return 0;
}
Here, the int variable isn't initialized—but that's fine, because you're just going to replace whatever value was there with 20. The key is that the pointer is initialized to point to the variable. In fact, you could just allocate some raw memory to point to, if you want:
int main(){
void *memory = malloc(sizeof(int));
int *ptr = (int *)memory;
*ptr = 20;
printf("%d", *ptr);
free(memory);
return 0;
}
First Program with comments
#include <stdio.h>
int main(){
int *ptr; //Create a pointer that points to random memory address
*ptr = 20; //Dereference that pointer,
// and assign a value to random memory address.
//Depending on external (not inside your program) state
// this will either crash or SILENTLY CORRUPT another
// data structure in your program.
printf("%d", *ptr); //Print contents of same random memory address
// May or may not crash, depending on who owns this address
return 0;
}
Second Program with comments
#include <stdio.h>
int main(){
int *ptr; //Create pointer to random memory address
int q = 50; //Create local variable with contents int 50
ptr = &q; //Update address targeted by above created pointer to point
// to local variable your program properly created
printf("%d", *ptr); //Happily print the contents of said local variable (q)
return 0;
}
The key is you cannot use a pointer until you know it is assigned to an address that you yourself have managed, either by pointing it at another variable you created or to the result of a malloc call.
Using it before is creating code that depends on uninitialized memory which will at best crash but at worst work sometimes, because the random memory address happens to be inside the memory space your program already owns. God help you if it overwrites a data structure you are using elsewhere in your program.
In the first example, ptr has not been initialized, so it points to an unspecified memory location. When you assign something to this unspecified location, your program blows up.
In the second example, the address is set when you say ptr = &q, so you're OK.
You can set a value for the pointer, but once you've asked for memory for it using "new". This is how your code should look
int main(){
int *ptr;
ptr = new int; //ask for memory
*ptr = 20;
printf("%d", *ptr);
return 0;
}

Resources