Connecting Tech Pros Worldwide Forums | Help | Site Map

a malloc'd struct pointer created inside can be free'd outside a function ???

Newbie
 
Join Date: Jan 2008
Posts: 14
#1: Jan 17 '08
(sorry about my english)
Hello, i am a newbie in C and i am trying to understand how to use free(...) and malloc(...) functions. In the following programm i successfully create a point of struct(local_train) which carries the firstblock and last block address of a double linked list(-wagon-wagon-wagon-) which carries points of structs(train_load) in each "wagon". I also successfuly enlarge this list (adding wagons)depending on the amound of load i want to carry and also i manage to retrieve the loads from inside the list and free the memory allocated for the "wagon" the list's memory blocks, but everytime i try to free the memory allocated for the point of struct(train_load) or the point of struct(local_train), an error occurs:

************************************************** ******************************************
error:

Debug Assertion Failed!

Program:...
File: dbgheap.c
Line:1279

Expression:_CrtIsValidHeapPointer(pUserData)

For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

************************************************** ******************************************
I am totaly sure i do not change the address in the local_train point of struct, so why does it fails to free it. I also have seen after testing that i can no pass a new address from function parameters outside like that:
examble
main()
{
*p1 = 1;
*p2 = 0;
function(p1,p2);
and expect that *p1 is now equal to *p2.
}

void function(void *param1, void *param2)
{
param1 = param2
}

************************************************** ******************************************
so please help me..., where i am wrong??? i would appreciate a correction in my followed sample code or an example if its no troublesome.

Thank you in advance.
************************************************** ******************************************
The code:
test.c

#include <stdio.h>
#include <malloc.h>
#include "train.h"

main(void)
{
TRAIN_T local_train;
LOAD_T train_load;
double *y, *y1;

local_train = creator();

* if i put here: free(local_train) it works perfectly, but if i put it bellow

y = load( local_train ,"7e56gdhs897" , sizeof(double) );
*y = 7.7777;
train_load = unload( local_train , "7e56gdhs897" );
y1 = train_load ->W_LOAD;
until now everything works as expected and *y == *y1 !

-> free(local_train); hear is where it allways fais and triggers the error.
}
************************************************** ******************************************
train.c

hear i post only the code related to the problem
the other two functions( ...load(...) and ...unload(...) ) work as expected.

void *creator(void)
{
newtrain = malloc(sizeof(TRAIN_T));
T_size = malloc(sizeof(long));
*T_size = 0;
newtrain ->T_SIZE = T_size;
return(newtrain);
}

************************************************** ******************************************

gpraghuram's Avatar
Expert
 
Join Date: Mar 2007
Location: Chennai
Posts: 1,258
#2: Jan 17 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


Hi,
You can free a pointer allocated inside a function outside that function(That is in calling function)
But as per your say u are able to delete it at one place and not in another place it means there is a memory corruption.

NOTE:
Whatever code u have given wont compile as there are couple of compiler errors

Raghuram
Newbie
 
Join Date: Jan 2008
Posts: 14
#3: Jan 17 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


thank you this is the complete code, can you tell me where the memory coruption occurs, please...
************************************************** ******************************************
test.c

#include <stdio.h>
#include <malloc.h>
#include "train.h"


main(void)
{
TRAIN_T local_train;
LOAD_T train_load;
int *x, *x1, *x2, *x3;
double *y, *y1;

local_train = creator();
x = load(local_train,"4589e72",sizeof(int));
*x = 45;
y = load(local_train,"7e",sizeof(double));
*y = 7.7777;
x2 = load(local_train,"45yh",sizeof(int));
*x2 = 18;
train_load = unload(local_train,"7e");
y1 = train_load ->W_LOAD;
train_load = unload(local_train,"45yh");
x3 = train_load ->W_LOAD;
train_load = unload(local_train,"4589e72");
x1 = train_load ->W_LOAD;
free(local_train);
}

************************************************** ******************************************
train.h

#ifndef _train_h
#define _train_h

#include "LList2.h"

typedef struct {LBlock2T T_FIRST; void *T_SIZE; LBlock2T T_LAST;} *TRAIN_T;
typedef struct {void *W_LOAD; void *W_IDENTIFICATION;} *LOAD_T;

void *creator(void);
void *load(TRAIN_T train, char *identification, size_t size);
void *unload(TRAIN_T train, char *identification);

#endif

************************************************** ******************************************

train.c

#include <stdio.h>
#include <malloc.h>
#include "train.h"

void *kill_train(TRAIN_T train);
void *kill_lastwagon(TRAIN_T train);
void *kill_firstwagon(TRAIN_T train);
void *destroy(TRAIN_T train);

TRAIN_T newtrain;
LOAD_T previusload, nextload, lastload;
LBlock2T nextwagon, firstwagon, lastwagon, firstwagon2, lastwagon2;
long *T_size;
char *T_identity, *T_identity2;

void *creator(void)
{
newtrain = malloc(sizeof(TRAIN_T));
T_size = malloc(sizeof(long));
*T_size = 0;
newtrain ->T_SIZE = T_size;
return(newtrain);
}

void *load(TRAIN_T train, char *identification, size_t size)
{
long n;

n = 0;
T_size = train ->T_SIZE;
if( *(T_size) == 0)
{
train ->T_FIRST = NList2(NULL,1,f);
train ->T_LAST = NList2(newtrain ->T_FIRST,1,l);
}
else
{
previusload = train ->T_LAST ->value;
n = *T_size;
train ->T_LAST = NList2(train ->T_LAST,2,l);
}
nextload = malloc(sizeof(LOAD_T));
nextload ->W_IDENTIFICATION = identification;
n++;
*T_size = n;
train ->T_SIZE = T_size;
train ->T_LAST ->value = nextload;
nextload ->W_LOAD = malloc(size);
return(nextload ->W_LOAD);
}

void *unload(TRAIN_T train, char *identification)
{
previusload = train ->T_FIRST ->value;
lastload = train ->T_LAST ->value;
T_size = train ->T_SIZE;
T_identity = previusload ->W_IDENTIFICATION;
T_identity2 = lastload ->W_IDENTIFICATION;
if(*(T_size) == 1)
{
--*(T_size);
train ->T_SIZE = T_size;
free(train ->T_FIRST);
return(previusload);
}
else if(!strcmp(T_identity,identification))
{
--*(T_size);
train ->T_SIZE = T_size;
firstwagon = ILocBlock2(train ->T_FIRST,2,n);
free(train ->T_FIRST ->previus);
free(train ->T_FIRST);
train ->T_FIRST = firstwagon;
firstwagon->previus = NULL;
return(previusload);
}
else if(!strcmp(T_identity2,identification))
{
--*(T_size);
train ->T_SIZE = T_size;
lastwagon = ILocBlock2(train ->T_LAST, 2, p);
free(train ->T_LAST ->next);
free(train ->T_LAST);
train ->T_LAST = lastwagon;
lastwagon ->next = NULL;
return(lastload);
}
else
{
nextwagon = train ->T_FIRST;
while(strcmp(T_identity,identification) && (nextwagon != NULL))
{
nextwagon = nextwagon ->next;
nextload = nextwagon ->value;
T_identity = nextload ->W_IDENTIFICATION;
}
if(nextwagon == NULL)
return(NULL);
else
{
--*(T_size);
train ->T_SIZE = T_size;
firstwagon2 = FLBlock2(nextwagon ->previus,nextwagon,f);
lastwagon = FLBlock2(nextwagon ->previus,nextwagon,l);
lastwagon2 = FLBlock2(nextwagon,nextwagon ->next,l);
firstwagon = FLBlock2(nextwagon,nextwagon ->next,f);
LLBlock2(lastwagon,firstwagon);
free(firstwagon2);
return(nextload);
}
}
}

************************************************** ******************************************

LList2.h

#ifndef _LList2_h
#define _LList2_h

#include <stdlib.h>

typedef struct {void *previus; void *value; void *next;} *LBlock2T;
typedef enum {n, p, f, l} optionT;

void *NBlock(size_t size);
LBlock2T NLBlock2();
void LLBlock2(LBlock2T Block1,LBlock2T Block2);
void *FLBlock2(LBlock2T Block1,LBlock2T Block2,optionT option);
void *NList2(LBlock2T lastblock,long index,optionT option);

#endif

************************************************** ******************************************

LList2.c

#include <stdio.h>
#include "LList2.h"

static LBlock2T lb;
static optionT option;

void *NBlock(size_t size)
{
void *Block;

Block = malloc(size);
if(Block == NULL)
{
printf("no memory available\n");
return(NULL);
}
else return(Block);
}

LBlock2T NLBlock2()
{
return((LBlock2T) NBlock(sizeof(*lb)));
}

void LLBlock2(LBlock2T Block1,LBlock2T Block2)
{
Block1 -> next = Block2;
Block2 -> previus = Block1;
}

void *FLBlock2(LBlock2T Block1,LBlock2T Block2,optionT option)
{
LBlock2T block;

switch (option)
{
case f:
Block1 -> next = NULL;
block = Block2;
break;
case l:
Block2 -> previus = NULL;
block = Block1;
break;
}
return(block);
}

void *NList2(LBlock2T firstblock,long index,optionT option)
{
LBlock2T block, nextblock, previusblock;
int i;

switch (option)
{
case f:
block = NLBlock2();
block -> previus = NULL;
break;
case l:
nextblock = firstblock;
for(i=0;i<(index-1);i++)
{
nextblock -> next = NLBlock2();
previusblock = nextblock;
nextblock = nextblock -> next;
nextblock -> previus = previusblock;
}
nextblock -> next = NULL;
block = nextblock;
break;
}
return(block);
}

************************************************** ******************************************
Moderator
 
Join Date: Mar 2007
Location: North Bend Washington USA
Posts: 5,366
#4: Jan 17 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


Quote:

Originally Posted by dreiko466

I am totaly sure i do not change the address in the local_train point of struct, so why does it fails to free it. I also have seen after testing that i can no pass a new address from function parameters outside like that:
examble
main()
{
*p1 = 1;
*p2 = 0;
function(p1,p2);
and expect that *p1 is now equal to *p2.
}

void function(void *param1, void *param2)
{
param1 = param2
}

p1 and p2 are not changed because when you called the function a copy was made for each pointer. The copies are named param1 and param2. All the function does is change the copy.

To have the function change p1 and p2, you have to pass in the address of the variables. The function argument type now has to be the address of a pointer.
Expand|Select|Wrap|Line Numbers
  1. void function(void **param1, void **param2)
  2. {
  3. *param1 = *param2;
  4. }
  5.  
Newbie
 
Join Date: Jan 2008
Posts: 14
#5: Jan 17 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


Quote:

Originally Posted by weaknessforcats

p1 and p2 are not changed because when you called the function a copy was made for each pointer. The copies are named param1 and param2. All the function does is change the copy.

To have the function change p1 and p2, you have to pass in the address of the variables. The function argument type now has to be the address of a pointer.

Expand|Select|Wrap|Line Numbers
  1. void function(void **param1, void **param2)
  2. {
  3. *param1 = *param2;
  4. }
  5.  


thank you very much, you have helped me again to overcome my code problem, thank you,

so if i pass the local_train like that there would be no memory leaks, thank you i will try it and reply again for the results.
Newbie
 
Join Date: Jan 2008
Posts: 14
#6: Jan 17 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


Quote:

Originally Posted by dreiko466

thank you very much, you have helped me again to overcome my code problem, thank you,

so if i pass the local_train like that there would be no memory leaks, thank you i will try it and reply again for the results.

I tried it but i still cannot free(local_train) and the local_train cannot be free'd after it passes through the first load(...) fuction even if i pass the struct local_train inside onother pointer like for examble
void **depot

depot = malloc(depot);
*depot = local_train;

... = load(depot,.....)

void *load(void **depot,......)
{
free(*depot) not working the same error.
....
....
}

so why is this allocated memory local_train being corrupted and where?
can somebody help me please? thank you.
gpraghuram's Avatar
Expert
 
Join Date: Mar 2007
Location: Chennai
Posts: 1,258
#7: Jan 18 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


Quote:

Originally Posted by dreiko466

I tried it but i still cannot free(local_train) and the local_train cannot be free'd after it passes through the first load(...) fuction even if i pass the struct local_train inside onother pointer like for examble
void **depot

depot = malloc(depot);
*depot = local_train;

... = load(depot,.....)


void *load(void **depot,......)
{
free(*depot) not working the same error.
....
....
}

so why is this allocated memory local_train being corrupted and where?
can somebody help me please? thank you.


Hi,
i tried compiling the cde but it is giving linker error for the function ILocBlock2.
Are u using any more files for this

Raghuram
Newbie
 
Join Date: Jan 2008
Posts: 14
#8: Jan 18 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


Quote:

Originally Posted by gpraghuram

Hi,
i tried compiling the cde but it is giving linker error for the function ILocBlock2.
Are u using any more files for this

Raghuram

Sorry missed that....

The ILocBlock is located in the LList2.c :

code :

void *ILocBlock2(LBlock2T block,long index,optionT option)
{
int i;

switch (option)
{
case n:
for(i=0;i<(index-1);i++)
block = (block -> next);
break;
case p:
for(i=0;i<(index-1);i++)
block = (block -> previus);
break;
}
return(block);
}

and in the header file LList2.h:

void *ILocBlock2(LBlock2T Block1,long index,optionT option);

now i believe is fully builtable.

thank you for your concern.
gpraghuram's Avatar
Expert
 
Join Date: Mar 2007
Location: Chennai
Posts: 1,258
#9: Jan 18 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


The basic problem is the way you allocate the memory for the structure.
Expand|Select|Wrap|Line Numbers
  1. newtrain = malloc(sizeof(TRAIN_T));
  2. //Here size of TRAIN_T is 4 as it is a pointer
  3. //This is the problem as you do a memory corruption as you access member 
  4. //vaiables of the structure
  5.  
So what you have to do is in the declaration you have to change the *TRAIN_T and move the typedef separately like this

Expand|Select|Wrap|Line Numbers
  1.  
  2. typedef struct train_t
  3. {
  4.         LBlock2T T_FIRST;
  5.         void *T_SIZE;
  6.         LBlock2T T_LAST;
  7. } ST_TRAIN_T;
  8.  
  9. typedef struct train_t *TRAIN_T;
  10.  
  11.  
I think this helps


Raghuram
Newbie
 
Join Date: Jan 2008
Posts: 14
#10: Jan 18 '08

re: a malloc'd struct pointer created inside can be free'd outside a function ???


Quote:

Originally Posted by gpraghuram

The basic problem is the way you allocate the memory for the structure.

Expand|Select|Wrap|Line Numbers
  1. newtrain = malloc(sizeof(TRAIN_T));
  2. //Here size of TRAIN_T is 4 as it is a pointer
  3. //This is the problem as you do a memory corruption as you access member 
  4. //vaiables of the structure
  5.  
So what you have to do is in the declaration you have to change the *TRAIN_T and move the typedef separately like this

Expand|Select|Wrap|Line Numbers
  1.  
  2. typedef struct train_t
  3. {
  4.         LBlock2T T_FIRST;
  5.         void *T_SIZE;
  6.         LBlock2T T_LAST;
  7. } ST_TRAIN_T;
  8.  
  9. typedef struct train_t *TRAIN_T;
  10.  
  11.  
I think this helps


Raghuram

Thank you thats the solution, i understand that by changing newtrain = malloc(sizeof(TRAIN_T)) to (sizeof(ST_TRAIN_T)) the memory is allocated correctly
and free(...) works perfectly.

Thank you again Raghuram , problem solved.
Reply