Memory allocation/reallocation

This is a discussion on Memory allocation/reallocation within the C Programming forums, part of the General Programming Boards category; I'm still learning about pointers and using malloc, so please bare with me. I was wondering if it is possible ...

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    45

    Memory allocation/reallocation

    I'm still learning about pointers and using malloc, so please bare with me.

    I was wondering if it is possible to allocate memory for a pointer in a main function, send that pointer to another function, and then reallocate memory for that same pointer within the secondary function. I assume that this would make no difference to reallocating memory in the main function, correct?

    I'm having trouble reallocating memory for a few pointers that I am sending to a secondary function. I am basically collecting user input in the form of arrays (pointers, actually) and then planning to use these pointers to do some calculations in other functions. The problem is that the values are not storing correctly. I get no compiler error, but when i get to the memory reallocation line in the program, I get a segmentation fault and my compiler goes crazy. Obviously, I'm not using malloc and/or realloc correctly, even though I thought I had the right format, based on looking at other code snippets and what not.

    Here's my code...sorry for the complex variables, this project I'm working on is a MatLab simulation program conversion.

    main function:
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include"untitledproto.h"
    
    #include"untitled2.c"
    
    
    int main()
    {
    
    int M, i, j, PAS_type, cluster_number;
    double *d_norm, *delta_phi_deg, *amplitude_cluster, *phi_deg, *AS_deg;
    
    
    d_norm = malloc(sizeof(d_norm));
    delta_phi_deg = malloc(sizeof(delta_phi_deg));
    amplitude_cluster = malloc(sizeof(amplitude_cluster));
    phi_deg = malloc(sizeof(phi_deg));
    AS_deg = malloc(sizeof(AS_deg));
    
    
    if (d_norm==NULL)    /*checking for null pointers*/
    printf("OUT OF MEMORY!");
    
    if (delta_phi_deg==NULL)
    printf("OUT OF MEMORY!");
    
    if (amplitude_cluster==NULL)
    printf("OUT OF MEMORY!");
    
    if (phi_deg==NULL)
    printf("OUT OF MEMORY!");
    
    if (AS_deg==NULL)
    printf("OUT OF MEMORY!");
    
    
    ---------------------------------------------------------------------------------
    int data;
    
    data=dialog(d_norm, delta_phi_deg, amplitude_cluster, phi_deg, AS_deg);
    
    cluster_number = (data&#37;100)%10;
    M=((data-cluster_number)%100)/10;
    PAS_type=(data-(M+cluster_number))/100;
    
    
    
    return 0;
    }

    secondary function...supposed to gather user input and store them as arrays (basically).
    Returns one value that is basically a mathematical combination of the array sizes and another variable. This value is then split back apart into 3 separate variable in the main function. (I needed a multiple return).
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    
    
    double dialog(double *d_norm, double *delta_phi_deg, double *amplitude_cluster, double *phi_deg, double *AS_deg)
    {
    	
    	double spacing=0;
    	int M=0, PAS_type=0, cluster_number=0; 
    	int i,j;
    
    	while(M<=1)
    	{
    	
    		printf("\nNumber of elements?\t");
    		scanf("%d", &M);
    	}
    
    	
    	d_norm=realloc(d_norm, M*sizeof(d_norm));
    
    
    	if(M>1)
    	{
    	
    		while(spacing<=0)
    		{
    
    			printf("\nNormalized spacing between elements (in wavelengths)?\t");
    			scanf("%lf", &spacing);
    
    	
    
    			/*---------Computes Linearly Spaced Vector-------*/
    			
    
    			for(i=0; i<M; i++)
    			{
    				d_norm[i] = (i)*spacing;
    			}
    			
    
    	
    			while(cluster_number<1)
    			{
    
    				printf("\nNumber of impinging clusters of waves?\t");
    				scanf("%d", &cluster_number);
    		
    			}
    
    			delta_phi_deg = realloc(delta_phi_deg, cluster_number*sizeof(delta_phi_deg));
    				amplitude_cluster = realloc(amplitude_cluster, cluster_number*sizeof(cluster_number));
    				phi_deg = realloc(phi_deg, cluster_number*sizeof(phi_deg));
    				AS_deg = realloc(AS_deg, cluster_number*sizeof(AS_deg));
    
    			/*----------------^^^ Crashes here ^^^--------------------*/
    			PAS_type=0;
    	
    			while(PAS_type<1 || PAS_type>3)
    			{
    	
    			printf("\nPAS type (1 = Uniform, 2 = Gaussian, 3 = Laplacian)?\t");
    			scanf("%d", &PAS_type);
    
    			}
    
    			if(cluster_number==1)
    			{
    				if(PAS_type!=1)
    				{
    					delta_phi_deg[0]=-1;
    					while(delta_phi_deg[0]<=0)
    					{
    						printf("\nHalf Domain Definition (in degrees)?\t");
    						scanf("%lf", &delta_phi_deg[0]);
    				
    					}
    				}
    				else
    				{
    					delta_phi_deg[0]= 90;
    				}
    
    				amplitude_cluster[0]=1;
    
    				printf("\nMean Angle of Incidence at Node B (in degrees)?\t");
    				scanf("%lf", &phi_deg[0]);
    
    				AS_deg[0]=-1;
    				while(AS_deg[0]<0)
    				{
    					printf("\nAzimuth Spread (in degrees)?\t");
    					scanf("%lf", &AS_deg[0]);
    				}
    			}
    			else
    			{
    		
    				for(j=0;j<cluster_number;j++)
    				{
    					if(PAS_type!=1)
    					{
    					
    						delta_phi_deg[j]=-1;
    						while(delta_phi_deg[j]<0)
    						{
    							printf("\nCluster %d/%d: Half Domain Definition (in degrees)?\t", j+1, cluster_number);
    							scanf("%lf", &delta_phi_deg[j]);
    						}
    
    					}
    
    					else
    					{
    						delta_phi_deg[j]= 90;
    					}
    
    
    					amplitude_cluster[j]=-1;
    					while(amplitude_cluster[j]<0)
    					{
    						printf("\nCluster %d/%d: Linear Power?\t", j+1, cluster_number);
    						scanf("%lf", &amplitude_cluster[j]);
    	
    					}
    		
    			
    					printf("\nCluster %d/%d: Mean Angle of Incidence at Node B (in degrees)?\t", j+1, cluster_number);
    					scanf("%lf", &phi_deg[j]);
    
    			
    					AS_deg[j]=-1;
    					while(AS_deg[j]<0)
    					{
    						printf("\nCluster %d/%d: Azimuth Spread (in degrees)?\t", j+1, cluster_number);
    						scanf("%lf", &AS_deg[j]);
    					}	
    				}
    			}		
    		}
    	}
    
    
    
    int data=(M*10)+(PAS_type*100)+cluster_number;
    
    return data;
    }

    Thank you in advance, as well as sorry for my poor programming. I'm still learning...

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,699
    All the parameters passed to dialog() or passed by-value. This means that any changes made to these variables inside dialog() will not be seen by main(). For example:
    >> d_norm=realloc(d_norm, M*sizeof(d_norm));
    This may change the value of d_norm inside dialog() - but the "d_norm" variable in main() is still pointing to the original (now invalid) address. realloc() is free to return a brand new pointer.

    So you'll need to "pass by reference" any parameters whose values change, and those changes need to be seen by the caller.

    gg

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    What happens is that realloc may move the memory contents to some other place in memory but main won't know that. If this happens the pointer in main becomes a wild or dangling pointer.

    The function should therefore take a pointer to pointer so that the pointer in the calling code would be updated.

    Code:
    void foo(int** pp)
    {
        //realloc
    }
    
    int main(void)
    {
        int* p = malloc(N);
        foo(&p); //foo may change where p points
    }
    Another issue is that if realloc fails to allocate more data it returns NULL but doesn't change the original memory.

    Code:
    d_norm=realloc(d_norm, M*sizeof(d_norm));
    If that should happen you have just lost a reference to the original memory.

    Instead store the result in a different pointer and assign it back only if it is not NULL

    Code:
    double* sizer = realloc(dnorm, M);
    if (sizer == NULL) {
        //realloc failed
    }
    else {
        dnorm = sizer;
    }
    And the third issue
    Code:
    d_norm = malloc(sizeof(d_norm));
    //and elsewhere
    Did you want to allocate a double's worth of memory (sizeof(*d_norm)) or a pointer-to-double's worth of memory (which might not be enough to store a double)?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    Registered User
    Join Date
    Jun 2008
    Posts
    45
    Quote Originally Posted by Codeplug View Post
    So you'll need to "pass by reference" any parameters whose values change, and those changes need to be seen by the caller.

    gg
    My compiler gives me an error when I try to send the addresses of the pointers. It says that I'm passing from incompatible pointer types.

    That's what you meant when you said passing by reference, correct?

  5. #5
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,211
    You have to change the function prototype/definition as well.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    Quote Originally Posted by magda3227 View Post
    My compiler gives me an error when I try to send the addresses of the pointers. It says that I'm passing from incompatible pointer types.

    That's what you meant when you said passing by reference, correct?
    When you "send the addresses of pointers", you need to make the function you're calling expect to receive pointers-to-pointers, as anon outlined.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    Jun 2008
    Posts
    45
    I made the changes so that the second function accepts a pointer to a pointer. But how does this change the way I store the values? I'll have to change the notation for incrementing the pointer and what not, won't I? How would I get these values back to the original pointer in the main function?

    Sorry if I'm asking too many questions, but no books or sources I can find cover this...

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    anon has explained it rather well. Basically, you pass a pointer-to-pointer to the function that needs to modify the value (i.e., use realloc()). Everywhere in that function that you need to use the pointer, you use *p instead of p. [1]

    The changes are automatically reflected in the calling function (main), because by using *p, you're actually modifying the variable in main. Strange, but true.

    [1] Note: *p++ doesn't work. You need to use (*p)++ or else *p+=1.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,211
    Example without testing the code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void allocdouble(double **d, double v);
    
    void allocdouble(double **d, double v)
    {
        *d = malloc(sizeof(**d)); /* Corrected error of allocating the wrong amount */
        if(*d)
        {
            **d = v;
        }
        else *d = NULL;
    }
    
    int main(void)
    {
        double *d;
    
        allocdouble(&d, 5.0);
        if(d != NULL)
        {
            printf("*d = &#37;f\n", *d);
            free(d);
        }
        else printf("Allocation failed\n");
    
        return 0;
    }
    Last edited by MacGyver; 07-04-2008 at 04:28 PM. Reason: Correction

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    It's just the same as with normal variables. If you want the function to modify them so that the modifications are visible to the caller you pass a pointer to the variable.

    With the pointers you simply add +1 level of indirection. There are two things that can be modified: the data that the pointer points to, and where the pointer itself points to.

    With variables
    Code:
    #include <stdio.h>
    
    void by_value(int n)
    {
        ++n;
    }
    
    void by_pointer(int* n)
    {
        ++*n;
    }
    
    int main(void)
    {
        int n = 1;
        printf("&#37;d ", n); /* n == 1 */
        by_value(n);
        printf("%d ", n); /* still n == 1 */
        by_pointer(&n);
        printf("%d\n", n); /* now n == 2 */
        return 0;
    }
    With pointers
    Code:
    #include <stdio.h>
    
    void by_value(char* n)
    {
        ++n;
    }
    
    void by_pointer( char** n)
    {
        ++*n;
    }
    
    int main(void)
    {
        char str[] = "ABC";
        char* p = str;
        printf("%c ", *p); /* points to 'A' */
        by_value(p);
        printf("%c ", *p);  /* still points to 'A' */
        by_pointer(&p);
        printf("%c\n", *p); /* now points to 'B' */
        return 0;
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  11. #11
    Registered User
    Join Date
    Jun 2008
    Posts
    45
    Thank you to all who responded.

    Your explanations were very helpful, especially the examples you provided. I learn visually, and they really helped me to understand what's going on and the differences between the two types of increments.

    Pointers still seem very complex to me, but they're definitely really useful if you can master them.

    Thank you once again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 01-13-2008, 02:14 AM
  2. Question regarding Memory Leak
    By clegs in forum C++ Programming
    Replies: 29
    Last Post: 12-07-2007, 01:57 AM
  3. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  4. Shared Memory - shmget questions
    By hendler in forum C Programming
    Replies: 1
    Last Post: 11-29-2005, 02:15 AM
  5. What's the best memory (RAM) type?
    By Unregistered in forum A Brief History of Cprogramming.com
    Replies: 17
    Last Post: 12-15-2001, 12:37 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21