#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2011
    Posts
    13
    Rep Power
    0

    I lose the last member of array via realloc


    When I realloc my void* array the (old) last number becomes rubbish.
    I dunno why because the 1 after it is fine. only the one that
    used to be last prior to malloc.

    Now most was given to work on as class assignment
    I will say when it is my code.

    this is the struct I am using:

    Code:
    typedef struct 
    {
    	void** arr;
    	int typeSize;
    	int logicalSize;
    	int phisicalSize;
    
    	void (*print)(const void*);
    	void (*save)(FILE*, const void*);
    	void* (*load)(FILE*);
    } Array;

    some given functions (I didn't add anything and am not allowed to):

    Code:
    void printInt(const void* obj)
    {
    	printf("%d ", *(int*)obj);
    }
    Code:
    void saveInt(FILE* f, const void* obj)
    {
    	fwrite(obj, sizeof(int), 1, f);
    }
    Code:
    void* loadInt(FILE* f)
    {
    	int* newValue = (int*)malloc(sizeof(int));
    	fread(newValue, sizeof(int), 1, f);
    	return newValue;
    }

    this is the initialization function (I only added the body)

    Code:
    void initArray(Array* arr, int sizeType, int phisicalSize, 
    			   void (*print)(const void*), void (*save)(FILE*, const void*), void* (*load)(FILE*))
    {
    	int i=0;
    
    	arr->phisicalSize=phisicalSize;
    	arr->typeSize=sizeType;
    	arr->logicalSize=0;
    
    	arr->arr=(void**)malloc(arr->typeSize);
    	
    	for(i=0 ; i< (arr->phisicalSize) ; i++)	
    	{
    		arr->arr[i]=(void*)malloc(arr->typeSize);
    		arr->arr[i]=0;
    	}
    
    	arr->save=saveInt;
    	arr->load=loadInt;
    	arr->print=printInt;
    	
    }

    and here is where the problem triggers or so I think
    (I added the body)

    Code:
    void addToEnd(Array* arr, void* newValue)
    {
    	if(arr->logicalSize==arr->phisicalSize)
    	{
    		arr->arr=(void*)realloc(arr->arr, (arr->typeSize) * (arr->phisicalSize*2));
    		arr->phisicalSize*=2;
    	}
    
    	arr->arr[arr->logicalSize]=*(int*)newValue;
    	arr->logicalSize++;
    
    }
    this is the main I am using (was given as whole I did not add a thing and as u can see most is not worked on yet--> I need to write the function given their signatures)

    Code:
    Array intArr;
    	Array intArrFromFile;
    	int n1=3, n2=8, n3=5;
    
    initArray(&intArr, sizeof(int), 2, printInt, saveInt, loadInt);
    
    	addToEnd(&intArr, &n1);
    	addToEnd(&intArr, &n2);
    
    	addToEnd(&intArr, &n3);
    
    	printArr(&intArr);
    	//saveArrToFile("intsArr.bin", &intArr);
    	//freeArray(&intArr);
    
    	//initArray(&intArrFromFile, sizeof(int), 2, printInt, saveInt, loadInt);
    	//printf("\nInt arr from file, before read:\n");
    //	printArr(&intArrFromFile);
    	//loadArrFromFile("intsArr.bin", &intArrFromFile);
    //	printf("Int arr from file, after read:\n");
    //	printArr(&intArrFromFile);
    //	freeArray(&intArrFromFile);

    on first print it gives:

    3 -842150451 5

    I tried printing right after adding the 2ed number and before adding the 3rd it printed just fine.

    it must b something obvious I miss -.-

    I think the problem is with the realloc and then with entering the newvalue.

    Nothing I try seems to work I guess I am missing the point here.
  2. #2
  3. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    8
    Rep Power
    0
    Hello

    There are lot of mistakes.

    First, you have to read the documentation on malloc and arrays

    arr->arr=(void**)malloc(arr->typeSize);

    ==> you have allocated 4 bytes (maybe not enough to hold another pointer if your computer is 64bits)

    for(i=0 ; i< (arr->phisicalSize) ; i++)
    {
    arr->arr[i]=(void*)malloc(arr->typeSize); ==> as void has no size, you should not be able to use arr[i] (it can't know if you're incrementing the address of 1, 4, 8 ... bytes)
    ==> you have allocated 4 bytes
    arr->arr[i]=0;
    ==> and there you replace the pointer you just got by 0 (you lost the address of the allocated space, the second malloc is useless
    }

    Anyway, the result of this function is that void ** arr has only a 4-bytes zone allocated (you can only put one integer) until our reallocate the pointer. The first integer is registered, but there is no place for the second (should be a segmentation fault).

    Here is a working code :

    Code:
    #include <stdio.h> #include <stdlib.h>  typedef struct  { 	void * arr; 	int typeSize; 	int logicalSize; 	int physicalSize;  	void (*print)(const void*); 	void (*save)(FILE*, const void*); 	void* (*load)(FILE*); } Array;  void printInt(const void* obj) { 	printf("%d \n", *(int*)obj); }  void saveInt(FILE* f, const void* obj) { 	fwrite(obj, sizeof(int), 1, f); }  void* loadInt(FILE* f) { 	int* newValue = (int*)malloc(sizeof(int)); 	fread(newValue, sizeof(int), 1, f); 	return newValue; }  void initArray(Array* arr, int sizeType, int physicalSize,  			   void (*print)(const void*), void (*save)(FILE*, const void*), void* (*load)(FILE*)) { 	int i=0;  	arr->physicalSize=physicalSize; 	arr->typeSize=sizeType; 	arr->logicalSize=0;  	arr->arr=(int *)malloc(arr->physicalSize * arr->physicalSize); 	 	/*for(i=0 ; i< (arr->phisicalSize) ; i++)	 	{ 		arr->arr[i]=(void*)malloc(arr->typeSize); 		arr->arr[i]=0; 	}*/  	arr->save=saveInt; 	arr->load=loadInt; 	arr->print=printInt; 	 }  void addToEnd(Array* arr, void* newValue) { 	if(arr->logicalSize==arr->physicalSize) 	{ 		arr->arr=(void*)realloc(arr->arr, (arr->typeSize) * (arr->physicalSize*2)); 		arr->physicalSize*=2; 	} 	int * tmp = arr->arr; 	tmp[arr->logicalSize]=*((int*)newValue); 	printf("tmp : %d\n", tmp[arr->logicalSize]); 	arr->logicalSize++;  }  int main(){ Array intArr; 	Array intArrFromFile; 	int n1=3, n2=8, n3=5, i; 	  initArray(&intArr, sizeof(int), 2, printInt, saveInt, loadInt);  	addToEnd(&intArr, &n1);   	addToEnd(&intArr, &n2);   	addToEnd(&intArr, &n3);  	int * tmp = intArr.arr; 	for(i=0;i<3;++i){ 		printInt(&tmp[i]); 	} 	//saveArrToFile("intsArr.bin", &intArr); 	//freeArray(&intArr);  	//initArray(&intArrFromFile, sizeof(int), 2, printInt, saveInt, loadInt); 	//printf("\nInt arr from file, before read:\n"); //	printArr(&intArrFromFile); 	//loadArrFromFile("intsArr.bin", &intArrFromFile); //	printf("Int arr from file, after read:\n"); //	printArr(&intArrFromFile); //	freeArray(&intArrFromFile); }
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2011
    Posts
    13
    Rep Power
    0
    Why do I change the 2ed alocation if I go

    arr->arr[i]=0?

    first arr is a pointer 2ed arr is a pointer and by going 2ed arr[i] is going where it points and placing 0 there as value.

    More than that I can;t manually place adresses or values (other than NULL and 0 is not NULL) as I please.

    So I do not understand this remark.

    It;s a bit hard taking the code as it is in 1 line but I will revice malloc and play around with it a bit more see if things become clearer.

    plus 2 integers were actually allocated prior to realloc but this could b due to it placing numbers sequentially without crushing after passing the length and only giving the illusion it works...

    my comp is 32 bit so this should work fine.
    And the array must stay general.
    I can't convert to int that is why I have pointers to functions that deal with int ,.. the places I left with int in my code (where it should have stayed general or using typesize) is only for debugging so I am sure it does what I want it to do.

    Thanks for the help.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2011
    Posts
    13
    Rep Power
    0
    So far so good seems to b working for now

    Code:
    void initArray(Array* arr, int sizeType, int phisicalSize, 
    			   void (*print)(const void*), void (*save)(FILE*, const void*), void* (*load)(FILE*))
    {
    	int i=0;
    
    	arr->phisicalSize=phisicalSize;
    	arr->typeSize=sizeType;
    	arr->logicalSize=0;
    
    	arr->arr=(void**)malloc(arr->typeSize*arr->phisicalSize);
    		
    	for(i=0;i<arr->phisicalSize;i++)
    	arr->arr[i]=(void*)malloc(arr->typeSize);
    
    	arr->save=saveInt;
    	arr->load=loadInt;
    	arr->print=printInt;
    	
    }
    Code:
    void addToEnd(Array* arr, void* newValue)
    {
    	
    	if(arr->logicalSize==arr->phisicalSize)
    	{
    		arr->arr=(void**)realloc(arr->arr, (arr->typeSize) * (arr->phisicalSize)*2);
    		arr->phisicalSize*=2;
    	}
    	
    	arr->arr[arr->logicalSize]=(void*)malloc(arr->typeSize);
    	arr->arr[arr->logicalSize]=newValue;
    
    	arr->logicalSize++;
    
    }
  8. #5
  9. Wiser? Not exactly.
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2001
    Location
    Bonita Springs, FL
    Posts
    5,932
    Rep Power
    4033
    Originally Posted by Lenjaku
    So far so good seems to b working for now
    Code:
    	arr->arr[arr->logicalSize]=(void*)malloc(arr->typeSize);
    	arr->arr[arr->logicalSize]=newValue;
    This, as was mentioned before, is a memory leak. You are allocating typeSize bytes and then assigning the address of that memory to the array index. Then on the next statement you overwrite that array index with the newValue, removing your reference to the allocated memory. Since you no longer have the reference to that memory, you have no way to free it and the memory is lost.

    Based on what I see of your code, your malloc line is unnecessary. You seem to be trying to create just a single-dimension array of pointers which means you only need the one malloc/realloc for the arr->arr pointer, not one for each element in the array.
    Recycle your old CD's, don't just trash them



    If I helped you out, show some love with some reputation, or tip with Bitcoins to 1N645HfYf63UbcvxajLKiSKpYHAq2Zxud
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2011
    Posts
    13
    Rep Power
    0
    Actually there were no instruction in this assignment as for how to deal with the arr**...

    my problem actually was , I was trying to get eh value out of newVal and couldn't so I got back what works without complaining which was getting the address

    As it should stay generic I can not cast to int but otherwise I don't know how to pass the value....then it see

    I wanted a pointer (in struct) to pointers array.

    For some odd reason I was stuck on a misleading thought that I need to initialize with malloc in order to insert a value without realizing (which is true for assigning any values in the area the pointer points to but wrong when assigning address to the pointer to hold)
    Dunno why I got stuck on that....


    Anyway thank u all now it works :) just removed the last malloc. I apply address anyway, as said X_X;
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2011
    Posts
    13
    Rep Power
    0
    Ok I am clueless and tired :eh:

    the function for the initialization is same as initArray above.

    the function to addToEnd is:

    Code:
    void addToEnd(Array* arr, void* newValue)
    {
    	
    	if(arr->logicalSize==arr->phisicalSize)
    	{
    		arr->arr=(void**)realloc(arr->arr, (arr->typeSize) * (arr->phisicalSize)*2);
    		arr->phisicalSize*=2;
    	}
    	
    	arr->arr[arr->logicalSize]=newValue;
    
    	arr->logicalSize++;
    
    }

    And I am trying to free with:

    Code:
    void freeArray(Array* arr)
    {	 
    	freeArrayAndData(arr);
    
    	free(arr->arr);
    }
    Code:
    void freeArrayAndData(Array* arr)
    {	
    	int i=0;
    	for(i=0;i<arr->logicalSize;i++)
    	free(arr->arr[i]);
    }
    I got the signatures as instructions (so the signatures must not b changed) and there is no info as for what they do so I assumed they work the way I tried to get them to work but something is wrong...


    the first arr is actually the struct...
    The struct is called ARRAY and has a field called:
    void** arr;
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2011
    Posts
    13
    Rep Power
    0
    I removed the malloc I had for void* and only left it for void** arr

    the problem comes later on when I try to load the saved array into the new array that the main creates...
    if u see it does use malloc to create the integer in the loaditn function itlsef....plus I have 2 different free functions (freearr and freearranddata) I must use somehow
    please refer to first post with all the functions and main

    I am at loss and really want to hand this work in this is the last quetion left I am laready after deadline ,
    instructor gave me more time to hand it in but -10 points as a result

    please help me with it I could still get 90 I don;t want to end with 80.
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2011
    Posts
    13
    Rep Power
    0
    I eventually got it right....apparently there were some functions that I thought I have to use them and for doing so I had to use malloc(void*)

    but in fact (as I finally got reply fr my emails -.-)

    the function freeArraandData was not supposed to even b there in the first place. Now all working fine.

    There was no need to dynamically allocate the arr->arr[i]
    malloc(void**) was enough.

    I couldn't; get the right answer when I was sure I had to use everything, without changing the main or adding functions... it was impossible and lead me to false conclusions.

    Thanks for those who helped me :)

IMN logo majestic logo threadwatch logo seochat tools logo