freeing memory

Discussion in 'Mac Programming' started by farmerdoug, Jan 16, 2010.

  1. farmerdoug macrumors 6502a

    Joined:
    Sep 16, 2008
    #1
    I get a segmentation error when I try to free memory. Any ideas. thanks
    Code:
    char **** allocate_memory (char ****array)
    
    {
    	
    int i,j,k;
    	
    	
    if( (array = (char ****) calloc(2500,sizeof(char***))) == NULL)
    {	
    	printf("no memory");
    	return(0);
    }	
    for( i = 0; i <2000; i++)
    {
    	if ((array[i] = (char ***) calloc(5, sizeof(char**))) == NULL)
    	{
    		printf("no memory");
    		return(0);
    	}
    	
    	for( j = 0; j < 5; j++)
    	{
    		if ((array[i][j] = (char **) calloc(45, sizeof(char*))) == NULL)
    		{
    			printf("no memory");
    			return(0);
    		}
    		
    		for( k = 0; k < 45; k++)
    		{
    			if ((array[i][j][k] = (char *) calloc(8, sizeof(char))) == NULL)
    			{
    				printf("no memory");
    				return(0);
    			}
    		}
    	}
    }
    	return ((char ****) array);
    }
    
    
    
    
    void freearrays( char ****array)
    {
    	int i, j,k;
    	
    	for (i = 0; i < 2500;i ++)
    	{
    		for(j = 0; j < 5; j ++)
    		{	
    			for (k = 0; k < 45; k++);
    				free(array[i][j][k]);
    			free(array[i][j]);
    		
    		}
    		free(array[i]);
    	}
    	
    	free(array);
    	
    }int main (int argc, const char * argv[]) {
        // insert code here...
    	
    //	char  line[1000], listname[50], tmp[1024];
    	
    	int i4, i5, m;
    	int i,j,k;
    	char filename[50];
    	FILE *fp; //, *action;
    	
    	
    /*	if (atoi (argv[0]) == 0)
    	{
    		printf("you forgot the date\n");
    		return(0);
    	}
     */	
    	Caverages = allocate_memory((char****)Caverages);
    	Paverages = allocate_memory((char****)Paverages);
    		freearrays((char ****)Paverages);
    	freearrays((char ****)Caverages);
    	
    
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    In your allocation you make enough room for 2500 char***s, but then only allocate and assign 2000. Then when you free, you try to access elements past 2000, free uninitialized pointers, etc. Also, you don't show where your arrays are declared, so you may or may not need to free array itself.

    -Lee
     
  3. farmerdoug thread starter macrumors 6502a

    Joined:
    Sep 16, 2008
    #3
    freeing memory

    Thanks. I defined pages (#define pages 2000) so that I don't have to worry about all keeping everything the same. It seems to work.
     
  4. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #4
    Where, and how, are 'Caverages' and 'Paverages' declared?

    What are their intended internal structure?

    Assuming your 'allocate_memory' function is correct your 'freearrays' functions has an semi-colon misplaced. Here it is reformatted - see if you can spot it?

    Code:
    void freearrays( char ****array)
    {
        int i, j, k;
    
        for (i = 0; i < 2500; i++)
        {
            for (j = 0; j < 5; j++)
            {
                for (k = 0; k < 45; k++)
                    ;
    
                free(array[i][j][k]);
                free(array[i][j]);
    
            }
    
            free(array[i]);
        }
    
        free(array);
    }
    
     
  5. autorelease macrumors regular

    Joined:
    Oct 13, 2008
    Location:
    Achewood, CA
    #5
    This is a memory allocation nightmare.

    It looks like you're trying to create a 2500-by-5-by-45 array of 8-character strings. Why allocate all the columns, rows, etc. individually when you can just allocate it in one block?

    Code:
    array = calloc(2500*5*45*8, sizeof(char));
    If you just want to be able to access each string like array[j][k], this should be fine.

    And for God's sake, make a typedef. Quadruple pointers are almost always a sign that things are very wrong. The better solution is to declare your multi-dimensional array as a one-dimensional array and use a macro to compute an (x,y,z) triple into a linear index.
     
  6. farmerdoug thread starter macrumors 6502a

    Joined:
    Sep 16, 2008
    #6
    freeing memory

    If I do that can I still address an element in the array as array[j][k] or do I have to use array[2000*i + 5*j + 45*k]?
     
  7. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #7
    Doug,

    Please answer the question that keeps getting asked and we can give you a useful answer.

    What is the format of the data that is being stored/accessed. We need to know your "intent".
     
  8. autorelease macrumors regular

    Joined:
    Oct 13, 2008
    Location:
    Achewood, CA
    #8
    You'd have to use array[2000*i + 5*j + 45*k]. C doesn't allow you to allocate multidimensional arrays with malloc(), since the size of an array must be constant at runtime in order for the x[j][k] notation to work.

    Since you know the array's size, you could just create a macro to compute the index for you, like this:

    Code:
    #define INDEX(i,j,k) ((2000*i)+(5*j)+(45*k))
    Then you'd use it like so:
    Code:
    array[INDEX(1,2,3)] = something;
    What you did in your previous example was allocate an array of pointers, with each pointer pointing to other arrays of pointers, etc. While this method would allow you to access elements via x[j][k] notation, the overhead of accessing an element this way is huge because the computer has to follow a chain of 3 pointers to get to the contents.

    Somewhat related: 99% of the time, you'll never need anything more than a double pointer. (e.g. for an array of strings). Triple pointers are usually only used to pass or refer to arrays of strings (double pointers) by reference. Anything more than that usually means there's a better way to solve your problem. :p
     
  9. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #9


    the computation involved is pretty negligible. The compromises should be understood, but I think the simplicity of accessing the elements is worth it. In some cases it is not.

    -Lee

    edit: back when farmerdoug started asking about this some of the compromises were discussed:
    http://forums.macrumors.com/showthread.php?t=844474

    edit 2: I just checked out the x86 ASM. Each dimension costs about 4 instructions. Two moves, a bit shift, and a load from memory. The memory cost is also worth considering, but overall if the app is not memory or CPU starved, I value programmer time over execution time as long as optimal runtime is not a requirement.
     
  10. farmerdoug thread starter macrumors 6502a

    Joined:
    Sep 16, 2008
    #10
    freeing memory

    The requirements on my programming skills have never pushed me to consider many or all of the issues being raised here. In addition, memory and speed seem to be increasing at a far greater rate than I can use. The speed of C with Snow Leopard is just so incredible. I am constantly amazed.

    I have some third party libraries that require the array[i*dim1 + j*dim2 ...]
    but I prefer array[j][k] - habit and its visually easier to read.

    lloyddean: as far as the type of data, I'm not sure why it would matter but in this case, I am reading csv files from which I am storing reduced and calculated data in 3d arrays of strings. The arrays have to be searched to find certain equal elements for further calculations.
     
  11. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #11
    That's pretty much the same thing as "each dimension costs a load from memory". Unless it's in the L2 cache and the load is hoisted, that load will be the majority of the execution time for those 4 instructions.

    I suspect a decent optimizing compiler will transform array[j][k] accesses in a loop into something else anyway if it's worthwhile.
     
  12. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #12
    All this talk of optimization and instruction counts strikes me as premature.

    The OP hasn't said anything about a speed problem. In fact, the only comment about speed is that "memory and speed seem to be increasing at a far greater rate than I can use."

    The problems the OP is having are all related to C's manual memory management (calloc/free), its primitive representation for strings, and one additional problem of evaluating strings as expressions at runtime (if I understand that problem correctly). All of those suggest using a higher-level language than plain ordinary C, IMNSHO.
     
  13. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #13
    Doug,

    You're still not stating the full nature of the data structures you're trying to work with. I believe you're confused and thus not able to state your problems sufficiently that we can understand it, leaving us confused as to how to assist you.
     

Share This Page