Thread: Trouble changing from Arrays to dynamic pointers

  1. #1
    Registered User
    Join Date
    Jun 2011
    Posts
    7

    Trouble changing from Arrays to dynamic pointers

    Hi i'm new here and would like to ask for your help. I have a running program which looks like this:
    Code:
    typedef struct{
    	double value;
    	double seqs[10];
    } SEQRANK;
    
    typedef struct{
    	...
    	double h[2*10];
    } CCDATA;
    
    int arrn[2];
    
    int calculateCC(CCDATA ccd[], int AorB){
    	int i,err=0;
    
    	...
    	
    back:
    	return err;
    }
    
    int findBestSeqs(SEQRANK sqr[], CCDATA ccd[], int AorB){
    	int i,err=0;
    	double TBuf[10];
    	double nBuf[10];
    
    	...
    
    back:
    	return err;
    }
    
    int main(void){
    	int i,err=0;
    	CCDATA CC[2];
    	SEQRANK SR[2*5];
    
    	...
    
    	for(i=0;i<2;i++){
    		err = calculateCC(CC,i);
    		if (err == 1){
    			printf("error in calculateCC\n");
    			goto back;
    		}
    
    		err = findBestSeqs(SR, CC, i);
    		if (err == 1){
    			printf("error in findBestSeqs\n");
    			goto back;
    		}
    	}
    	
    back:
    	return err;
    }
    As you see, the program is does everything two times (case A and B). A int is passed to the subfunction, indicating if its case A (=0) or case B (=1). I have a structure SEQRANK that consists of a sequence of doubles and a value, evaluating the the sequence. Accoarding to this value the sequence will end up in the corresponding place of SR[2*5]. First five slots are for the best sequences of case A, second five slots for case B. CC is also a structure array (CCDATA) with two datasets for the two cases. Right now the structures include arrays with a fixed length. But this length is not always the same for A and B and I find a dynamic solution more elegant, but having trouble to implement it. I have come up with this:

    Code:
    typedef struct{
    	double value;
    	double *seqs;
    } SEQRANK;
    
    typedef struct{
    	...
    	double *h;
    } CCDATA;
    
    int arrn[2];
    
    int calculateCC(CCDATA ccd[], int AorB){
    	int i,err=0;
    
    	ccd[AorB].h = malloc(2*arrn[AorB] * sizeof(double));
    	if (!ccd[AorB].h){
    		printf("Out of memory: ccd.h\n");
    		err = 1;
    		goto back;
    	}
    		
    	...
    	
    back:
    	return err;
    }
    
    
    
    int mallocSeqRank(SEQRANK sqr[], int AorB){
    	int i,err=0;
    	for(i=0;i<5;i++){
    		sqr[AorB*5+i].seqs = malloc(arrn[AorB] * sizeof(double));
    		if (!sqr[AorB*5+i].seqs){
    			printf("Out of memory: sqr->seqs\n");
    			err = 1;
    			goto back;
    		}
    	}
    back:
    	return err;
    }
    
    int freeSTRUCTS(SEQRANK sqr[], CCDATA ccd[]){
    	int i,j,err=0;
    
    	if(sqr){
    		for(i=0;i<2;i++){
    			for(j=0;j<5;j++){
    				free(sqr[i*5+j].seqs);
    			}
    		}
    	}
    
    	if(ccd){
    		for(i=0;i<2;i++){
    			free(ccd[i].h);
    		}
    	}
    	return err;
    }
    
    int findBestSeqs(SEQRANK sqr[], CCDATA ccd[], int AorB){
    	int i,err=0;
    
    	double *TBuf;
    	double *nBuf;
    
    	TBuf = malloc(arrn[AorB] * sizeof(double));
    	if (!TBuf){
    		printf("Out of memory: TBuf\n");
    		err = 1;
    		goto back;
    	}
    
    	nBuf = malloc(arrn[AorB] * sizeof(double));
    	if (!nBuf){
    		printf("Out of memory: nBuf\n");
    		err = 1;
    		goto back;
    	}
    
    
    	...
    
    back:
    	free(TBuf);
    	free(nBuf);
    	return err;
    }
    
    int main(void){
    	int i,err=0;
    	CCDATA CC[2];
    	SEQRANK SR[2*5];
    	
    	...
    	
    	for(i=0;i<2;i++){
    		err = mallocSeqRank(SR,i);
    		if (err == 1){
    			printf("error in mallocSeqRank\n");
    			goto back;
    		}
    	}
    
    	...
    
    	for(i=0;i<2;i++){
    		err = calculateCC(CC,i);
    		if (err == 1){
    			printf("error in calculateCC\n");
    			goto back;
    		}
    
    		err = findBestSeqs(SR, CC, i);
    		if (err == 1){
    			printf("error in findBestSeqs\n");
    			goto back;
    		}
    	}
    	
    back:
    	err = freeSTRUCTS(SR, CC);
    	return err;
    }
    Allocating the memory works but freeing wont. freeSTRUCT doesnt work.
    Furthermore, what I find very strange, the two buffers i need in findBestSeq TBuf and nBuf are allocate and freed the first time findBestSeq is called. But when its called the second time, to calculate case B, malloc wont allocate memory.
    Any help would be appreciated.
    Last edited by hpotsirhC; 06-14-2011 at 12:59 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    Which OS/Compiler are you using?

    If it's Linux/GCC, then I would suggest you start with
    gcc -g -Wall prog.c
    valgrind ./a.out

    valgrind is very good at spotting array overruns, use of uninitialised data and other kind of memory related programming mistakes.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jun 2011
    Posts
    7
    Oh so this is getting more complicated that I thought.
    I dont know too much about that technical side so excuse if my answers dont get the point.
    Im running Windows 7 and the Wascana/Eclipse IDE, using MinGW.
    Is that what you asked?

    Thanks

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    Yes.
    But unfortunately, those tools don't run on windows based systems.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I ran the example and malloc and free work fine. I checked the addresses and they match up.
    You have an issue with defining CC CC[2];. I'm surprised it compiled at all. It believe it should be CCDATA CC[2].

  6. #6
    Registered User
    Join Date
    Jun 2011
    Posts
    7
    Thanks nonoob. You are right its CCDATA CC[2], but I had it originallycorrect in my program as well. This is more an error that ocurred when I copied the code to this board.
    Strange that it works. So it must be because of parts I didnt include here because I thought they were fine.
    For example the TBuf and nBuf get sorted before being freed. I'll check that and be back.

    @Salem: I guess what you proposed is some kind of diagnose tool. Is there anything that'll work with my setup?

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,662
    MinGW uses the microsoft runtime, so you might be able to use this.

    But to get valgrind-like functionality on windows costs money.

    Here is a list, though I've no idea off-hand which would run on your setup.
    Memory debugger - Wikipedia, the free encyclopedia
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Jun 2011
    Posts
    7
    So I went thorugh the whole code again. I commented out everything apart from the malloc and free commands and it worked fine (I kept checking the addresses and if they were freed correctly). Then step by step I activated the program. So I found the line which seems to cause the problem. If its comment, the program runs. If the line is active it wont. And I dont understand why (I dont get error messages or warnings before). Some names have changed to the example above but the idea is the same. Here it is:

    Code:
    typedef struct{
    	double *hcc;
    	double *tcc;
    	double *fw_tot;
    	double *nStr;
    	double *intgrl;
    } COMPCURV;
    
    int arrn[2]
    
    int main(void){
            ...
    	int i,err=0;
    	COMPCURV CC[2];
    	for(i=0;i<2;i++){
    		err = calculateCompositeCurve(ft,CC,i);
    		if (err == 1){
    			printf("error in calculateCompositeCurve\n");
    			goto back;
    		}
    	}
    back:
    	return err;
    }
    
    int calculateCompositeCurve(TASKDATA tdata,COMPCURV CCdata[], int HorC){
    	int i,err=0;
    
    	CCdata[HorC].hcc = malloc(2*arrn[HorC] * sizeof(double));
    	if (!CCdata[HorC].hcc){
    		printf("Out of memory: CCdata.hcc\n");
    		err = 1;
    		goto back;
    	}    // this part is repeated for all pointers of COMPCURV CCdata
            ...
    	CCdata[HorC].hcc[0]=0;
    	CCdata[HorC].intgrl[0]=0;
    	for (i=1;i<2*arrn[HorC];i++){
    		CCdata[HorC].nStr[i]+=CCdata[HorC].nStr[i-1];
    		CCdata[HorC].fw_tot[i]+=CCdata[HorC].fw_tot[i-1];
    		CCdata[HorC].hcc[i]=CCdata[HorC].hcc[i-1]+(CCdata[HorC].tcc[i]-CCdata[HorC].tcc[i-1])*CCdata[HorC].fw_tot[i-1];
    		CCdata[HorC].intgrl[i] = CCdata[HorC].intgrl[i-1] + (CCdata[HorC].hcc[i] - CCdata[HorC].hcc[i-1]) * (CCdata[HorC].tcc[i]+CCdata[HorC].tcc[i-1]) / 2;
    	}
    back:
    	return err;
    }
    So its the last formula "CCdata[HorC].intgrl[i] = ...". Strange thing is, that it works when I change the pointers from the COMPCURV structure to arrays with fixed length.

  9. #9
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Did you malloc for intgrl and all the others: hcc, tcc, fw_tot, nStr ?
    Perhaps it would be easier if you change the structure:

    Code:
    typedef struct{
        double hcc;
        double tcc;
        double fw_tot;
        double nStr;
        double intgrl;
        } COMPCURV;
    
    COMPCURV CC[2][10];
    or
    COMPCURV *CC[2];
    CC[0] = malloc(sizeof(COMPCURV) * N);
    CC[1] = malloc(sizeof(COMPCURV) * N);
    That way you don't have to malloc separately for each element. Then you access elements by CC[0][0].hcc for example.

  10. #10
    Registered User
    Join Date
    Jun 2011
    Posts
    7
    Quote Originally Posted by nonoob View Post
    Did you malloc for intgrl and all the others: hcc, tcc, fw_tot, nStr ?
    Yes I casted malloc for all the pointer. And they are filled with the necessary data as well.

    Your other suggestions would save me some mallocs thats true. Ill try that later home, thanks

  11. #11
    Registered User
    Join Date
    Jun 2011
    Posts
    7
    @ nonoob: Youre the man. It works like this. Thanks a lot. As you said it saves me some malloc and free casts. The disadvantage is that now I cant simply memcopy for example the *hcc pointer but have to do it with a loop. I just had to change how the different bytes are addressed etc but concerning the calculations nothing has changed. Just how the memory is managed.
    Do you also have an explanation for this behaviour? Its just that I'd like to understand it as well.

  12. #12
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I don't know what you want to memcpy. But whatever, I think it should be easier this way. Less loops. Just assign... You can copy entire struct contents or struct member.
    What behaviour do you wish explained?

  13. #13
    Registered User
    Join Date
    Jun 2011
    Posts
    7
    What I mean is that before I could write
    Code:
    memcpy(dblPointer,CC[0].hcc,n)
    which now is
    Code:
    for(i=0;i<n;i++){
        dblPointer(i)=CC[0][i].hcc;
    }
    In the case of the CC strucutres its more likely that I want to copy for example all the hcc Values in a row and not a Structure with its different values. But I'm fine with the loop above. As long as it works its okay. What I meant with the mysterious behaviour is that before, when my Structure CC had pointers (of dynamic length) it didn't work but now - with the Structure pointers being of dynamic length - it does.

  14. #14
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    That's because all the hcc values are not contiguous any more. They are interleaved with tcc, fw_tot, and the rest of the structure members.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Having major trouble with double arrays using pointers
    By omegasli in forum C Programming
    Replies: 3
    Last Post: 04-09-2011, 08:49 PM
  2. dynamic output; changing without reprinting
    By frog in forum C++ Programming
    Replies: 5
    Last Post: 09-20-2010, 11:12 AM
  3. Arrays, pointers, trouble..
    By Aino in forum C Programming
    Replies: 2
    Last Post: 08-05-2010, 01:27 PM
  4. trouble initializing a dynamic array of pointers to NULL
    By supernater in forum C++ Programming
    Replies: 8
    Last Post: 09-13-2009, 04:47 PM
  5. Replies: 7
    Last Post: 06-04-2008, 10:39 PM