Thread: I can't fix this c code! Who can??

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Unhappy I can't fix this c code! Who can??

    Greetings.

    Am in dire need of help here. I have been building a certain system which is part of an RPC/PHP extension that creates memory-based matrices for certain data analysis purposes. Am not good in memory management code, I must admit in advance. And hence, am currently stuck in a notorious C's memory miry clay - for sure! All sorts of memory errors and bugs have plagued me for a while now. I need urgent help to finish this application within a few weeks.

    I have recreated, in the following much lesser code (below), to simulate the senario within the other code that seems to be the culprit. After compiling, with Intel C++ Compiler 9.1 or MS Studio 2003, I get the same type of access violation errors of all sorts, including: -
    "The thread 'Win32 Thread' (0x1520) has exited with code 0 (0x0).
    Unhandled exception at 0x7c910ef4 in WIN32ConsoleApp.exe: 0xC0000005: Access violation reading location 0xfffffff8."

    Where am I going wrong??? I can't seem to overcome this bug. I have to stick to C - no matter the rugged edges and bleeding corners. SOMEBODY HELP!!!


    Code:
    /* RECEIVE CONSOLE INPUT AND CREATE A MOCK REPRESENTATION MATRIX */ 
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #define EQL == /* Equal To */
    #define NEQL != /* Not Equal To */
    #define LOEQL <= /* Less Than or Equal To */
    #define GOEQL >= /* Greater Than or Equal To */
    
    typedef unsigned int uint;
    typedef signed int sint;
    
    #define e 2.718281828
    #define ROWS 5
    #define COLS 5
    #define MAX_INPUT_LEN 254
    
    void deallocate2D(double **array, int nrows) {
    
    	/*  deallocate each row  */
    	int i;
    	for(i = 0; i < nrows; i++) {
    		free(array[i]);
    		array[i]=NULL;
    	}
    	/*  deallocate array of pointers  */
    	free(array);
    	array=NULL;
    }
    
    void deallocate2C(char **array, int nrows) {
    
    	/*  deallocate each row  */
    	int i;
    	for(i = 0; i < nrows; i++) {
    		free(array[i]);
    		array[i]=NULL;
    	}
    	/*  deallocate array of pointers  */
    	free(array);
    	array=NULL;
    }
    
    void quitapp(uint rowcnt,double **mem2Dblock_a,char **mem2Dblock_b)
    {
    	deallocate2D(mem2Dblock_a,rowcnt);
    	deallocate2C(mem2Dblock_b,rowcnt);
    	fcloseall();
    	fprintf(stderr,"\nCleaned up.\nExiting.\nBye!");
    	exit(0);
    }
    
    void restartapp(char *appexec,uint rowcnt,double **mem2Dblock_a,char **mem2Dblock_b)
    {
    	deallocate2D(mem2Dblock_a,rowcnt);
    	deallocate2C(mem2Dblock_b,rowcnt);
    	fcloseall();
    	system(appexec);
    	exit(0);
    }
    
    int main(int argc,char *argv[])
    { 
    	static uint i=0,j=0,k=0,m=0,n=0,lastknown_rows=0,lastknown_cols=0,lastknown_dims=0,outputlen=0,ramgrowth=0;
    	size_t inputlen;
    	char **kylst=malloc(sizeof(char*)*1);
    	double **kbmtx=malloc(sizeof(double*)*1);
    	char buff[MAX_INPUT_LEN];
    
    	char *dimfilenm = "~dim.tmp";
    	char *kyfilenm = "~ky.lst";
    	char *kbfilenm = "~kb.bin";
    	char *outfilenm = "~out.tmp";
    	FILE *kbfile=NULL;
    	FILE *dimfile=NULL;
    	FILE *kyfile=NULL;
    	FILE *outfile=NULL;
    
    	if(argc==2)
    	{
    		if(((dimfile=fopen(dimfilenm, "r")) NEQL NULL) && (lastknown_dims=fscanf(dimfile,"%d %d",&lastknown_rows,&lastknown_cols))EQL 2)
    		{
    			m=lastknown_rows;
    			n=lastknown_cols;
    			printf("/* Found a valid DIM file showing %dx%d to be the last known dimensions */\n",m,n);
    			printf("/* Locate and try reading the stored KY list file */\n");
    			if((kyfile = fopen(kyfilenm, "r")) EQL NULL) 
    			{ 
    				m=0;
    				n=0;
    				if((kyfile = fopen(kyfilenm, "w")) NEQL NULL) 
    				{ 
    					printf("/* Created a new KY list file */\n");
    					//restartapp(argv[0],m,kbmtx,kylst); 
    					if((kbfile = fopen(kbfilenm, "wb")) NEQL NULL) 
    					{ 
    						printf("/* Created a new KB list file */\n");
    						//restartapp(argv[0],m,kbmtx,kylst); 
    						printf("/* Please restart %s to proceed */\n",argv[0]);
    						fprintf(dimfile,"%d %d\n",m,n);
    						quitapp(m,kbmtx,kylst);
    					}  else {
    						fprintf(stderr, "/* Error creating a new KB list file */\n");
    						quitapp(m,kbmtx,kylst);
    					}
    				}  else { /* if((kyfile = fopen(kyfilenm, "w")) NEQL NULL) */
    					fprintf(stderr, "/* Error creating a new KY list file */\n");
    					quitapp(m,kbmtx,kylst);
    				}				
    				fclose(kbfile);
    			} else { /* if((kyfile = fopen(kyfilenm, "r")) EQL NULL) */
    				if(m>0&&n>0)
    				{
    					m=lastknown_rows;
    					n=lastknown_cols;
    					printf("/* Resize 'char** kylst' to accommodate the last known rows : %d */\n",m);
    					kylst=(char**)realloc(kylst,(size_t)(sizeof(char*)*(m)));
    					if(kylst EQL NULL)quitapp(m,kbmtx,kylst);	
    					k=0;
    					for(i=0;i<(m);i++)
    					{
    						k+=fscanf(kyfile,"%s",buff);
    						if(i > k) {i--; break;}
    						if((kylst[i] = (char *)malloc((size_t)((strlen(buff)+1)*sizeof(char)))) EQL NULL)quitapp(m,kbmtx,kylst);
    						strcpy(kylst[i],buff);
    					}
    					printf("/* Locate and try reading the stored KB data file */\n");
    					if((kbfile = fopen(kbfilenm, "rb")) NEQL NULL) 
    					{ 
    						printf("/* Resize 'double **kbmtx' to accommodate the last known dimensions : %dx%d */\n",m,n);
    						kbmtx=(double**)realloc(kbmtx,sizeof(double*)*m);
    						if(kbmtx==NULL)quitapp(m,kbmtx,kylst);
    						printf("/* Initialize KB with zeros. */\n");
    						for(i = 0; i < m; i++) 
    						{
    							kbmtx[i]=(double*)malloc(sizeof(double)*n);
    							if(kbmtx[i]==NULL) quitapp(m,kbmtx,kylst);
    							for(j = 0; j < n; j++)
    							{
    								kbmtx[i][j]=0.0;
    								printf("%lg\t",kbmtx[i][j]);
    							}
    							printf("\n");		
    						}
    						printf("/* Load the binary file data into KB, row by row. */\n");
    						for (i = 0; i < m; i++) 
    						{
    							if (fread(kbmtx[i], sizeof(double), n, kbfile) != n) 
    							{ 
    								fprintf(stderr, "Error writing to file."); 
    								quitapp(m,kbmtx,kylst);
    							} 
    						}
    
    						printf("/* Close the binary file */\n");
    						fclose(kbfile);
    
    						printf("/* Now print KB to the screen. */\n");
    						for (i = 0; i < m; i++) 
    						{
    							for(j = 0; j < n; j++)
    							{
    								printf("%lg\t",kbmtx[i][j]);
    							}
    							printf("\n");
    						}
    						printf("/* Show KB RAM addresses on the screen. */\n");
    						for (i = 0; i < m; i++) 
    						{
    							for(j = 0; j < n; j++)
    							{
    								printf("%d\t",&kbmtx[i][j]);
    							}
    							printf("\n");
    						}
    					}  else { /* if((kbfile = fopen(kbfilenm, "rb")) NEQL NULL) */
    						fprintf(stderr, "/* Cannot read the KB data file */\n");
    						quitapp(m,kbmtx,kylst);
    					}
    				}
    				fclose(kyfile);
    			}
    			fclose(dimfile);
    			puts("Type A New String and Press <ENTER> To Store in RAM and Binary File, ");
    			for(m=lastknown_rows,n=lastknown_cols;;m++,n++)
    			{
    				if((dimfile = fopen(dimfilenm, "w")) NEQL NULL)
    				{					
    					gets(buff);
    					inputlen=(strlen(buff)+1);
    					if(inputlen<MAX_INPUT_LEN)
    					{
    						if(strcmp(buff,"Q!") EQL 0)
    						{
    							quitapp(m,kbmtx,kylst);
    						}
    						if((kyfile = fopen(kyfilenm, "a")) NEQL NULL)
    						{
    							kylst=(char**)realloc(kylst,(size_t)(sizeof(char*)*(m+1)));
    							if(kylst EQL NULL)quitapp(m,kbmtx,kylst);
    							kylst[m]=(char*)malloc((size_t)(sizeof(char)*inputlen));
    							if(kylst[m] EQL NULL)quitapp(m,kbmtx,kylst);
    							strcpy(kylst[m],buff);
    							if((kbmtx=(double **)realloc(kbmtx,(size_t)((m+1)*sizeof(double*)))) NEQL NULL)
    							{
    								if((kbmtx[m]=(double *)malloc((size_t)((n+1)*sizeof(double)))) EQL NULL)quitapp(m,kbmtx,kylst);
    								for(i=0;i<(m+1);i++)
    								{
    									for(j=0;j<(n+1);j++)
    									{
    										kbmtx[i][j]=0.0;
    									}
    								}
    							} else quitapp(m,kbmtx,kylst);
    							printf("Committing to KY list file\n");
    							fprintf(kyfile,"%s\n",kylst[m]);
    							printf("/* Opening the KB binary data file for writing */\n");
    							if((kbfile = fopen(kbfilenm, "wb")) NEQL NULL) 
    							{ 
    								for(i=0;i<(m+1);i++)
    								{
    									if((fwrite(kbmtx[i],sizeof(double),(n+1),kbfile))!=(n+1))quitapp(m,kbmtx,kylst);
    								}	
    								fclose(kbfile);
    							} else {
    								fprintf(stderr, "Error opening KB file for updates."); 
    								quitapp(m,kbmtx,kylst); 
    							}						
    							fclose(kyfile);
    							fprintf(dimfile,"%d %d\n",m+1,n+1);
    							//lastknown_dims=flushall();					
    							//printf("/* Written %d updates to DIM file */\n",lastknown_dims);							
    							printf("/* Show KB RAM addresses on the screen. */\n");
    							for (i = 0; i < (m+1); i++) 
    							{
    								for(j = 0; j < (n+1); j++)
    								{
    									printf("%lg\t",kbmtx[i][j]);
    								}
    								printf("\n");
    							}
    							puts("Type and Store Another String Or Type Q! and <ENTER> To Quit: ");
    						} else printf("/* Oops! Cannot open KY list file for updates */\n");
    					} else { /* if(buff<MAX_INPUT_LEN) */
    						printf("/* Oops! Your input is too large. Keep it below 254 characters */\n");
    					}						
    				}  else printf("/* Oops! Cannot open DIM file for updates */\n");
    				fclose(dimfile);
    			}
    		} else { /* if(((dimfile=fopen(dimfilenm, "r+")) NEQL NULL) && (lastknown_dims=fscanf(dimfile,"%d %d",&lastknown_rows,&lastknown_cols))EQL 2) */
    			fprintf(stderr, "/* Cannot read or verify integrity of the DIM file */\n");
    			if((dimfile = fopen(dimfilenm, "w")) NEQL NULL) 
    			{ 
    				printf("/* Created a new DIM file */\n"); 
    				fprintf(dimfile,"%d %d\n",0,0);
    				printf("/* Please restart %s to proceed */\n",argv[0]);
    				quitapp(m,kbmtx,kylst);
    			}  else {
    				fprintf(stderr, "/* Error creating a new DIM file */\n");
    				quitapp(m,kbmtx,kylst);
    			}
    		}
    		quitapp(m,kbmtx,kylst);
    	}
    
    	return(0); 
    }

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I have no idea what is actually wrong with your code, but have you tried running the app in the debugger in visual studio?

    Also, the address you see indicates a negative offset off from a NULL pointer (8 bytes "back" from zero), which makes me think you are probably doing something wrong with a NULL pointer. Perhaps you are calling some function with a NULL that shouldn't be called with NULL? (fclose perhaps this:
    Code:
    			fclose(kbfile);
    Code:
    #define EQL == /* Equal To */
    #define NEQL != /* Not Equal To */
    #define LOEQL <= /* Less Than or Equal To */
    #define GOEQL >= /* Greater Than or Equal To */
    WHY on earth would this ever be a good idea?


    Code:
    void deallocate2C(char **array, int nrows) {
    ...
    	free(array);
    	array=NULL;
    }
    Setting array to NULL here is meaningless, as you are just about to leave the function, and the code you return to has the old copy of array, not the one set to NULL that only exist inside deallocate2C.

    I haven't gone through all of the code, those were just a few immediately obvious problems.

    Finally, your "restartapp" seems like a very poor idea. If you restart several times, you will have LOTS of copies of your app running - not a good idea.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Unhappy Thanks Matsp. I'll Check Again If NULL May Be Culprit

    Hi Matsp. Much appreciated your quick rescue response. Thanks man, you were first.

    Concerning...
    Debugger? Yes, I have tried the VS 2003 Debugger, Intel C++ Debugger and WinDbg to no much avail.

    I agree with you though for pointing out quite possibly where the bug might be coming from - some NULL pointer somewhere, or some NULL misuse. If that be so, I have gotten there for following 'sound' advice all over the net as to how 'best' to free heap'd memory by NULLing the pointer after free'ing it. I probably have abused otherwise good practice. I'll check out for my error.

    Concering...
    Code:
    #define EQL == /* Equal To */
    #define NEQL != /* Not Equal To */
    #define LOEQL <= /* Less Than or Equal To */
    #define GOEQL >= /* Greater Than or Equal To */
    ...I must say, in my humble opinion, this has saved me a lot of times in avoiding major typos bugs, like assignments (=) when I needed comparison (==), for instance. This approach, is actually well recommended in books like Deep C. So I type...

    Code:
    if((c EQL d)&&(c NEQL e)){}
    . It has worked well for me, but thanks for asking.

    Concerning...
    "restartapp", that is redundant code (probably invalid too), I have never used that piece of code, please ignore it. I doubt it would even work in the first place.

    Thanks again.

    Still worried though.

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by deendee View Post
    I agree with you though for pointing out quite possibly where the bug might be coming from - some NULL pointer somewhere, or some NULL misuse. If that be so, I have gotten there for following 'sound' advice all over the net as to how 'best' to free heap'd memory by NULLing the pointer after free'ing it.
    That IS a good practice, since you can at least check to see if a pointer has been free'd, if you set it to NULL right away. Otherwise, your bug here might be even more well hidden, presuming this is misuse of a free'd and NULL'd pointer. Instead of a bogus pointer, you'd have an overflow somewhere.

    So don't stop doing that!
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    pwning noobs Zlatko's Avatar
    Join Date
    Jun 2009
    Location
    The Great White North
    Posts
    132
    Your program contains a number of distinct sections. Some of which seem to be mutually exclusice in a run (in particular A A' and B B'). If you replace the the //SECTION commments with print statements, you could further narrow down the problem and you could get more help. This is a big piece of code you posted, so you might get faster help if you also post all input files and a what you're inputting at the keyboard. In short, a step by step process to reproduce the problem.

    Code:
    if(((dimfile=fopen(dimfilenm, "r")) NEQL NULL) && (lastknown_dims=fscanf(dimfile,"%d %d",&lastknown_rows,&lastknown_cols))EQL 2)
        {
            // SECTION A
            m=lastknown_rows;
            n=lastknown_cols;
            printf("/* Found a valid DIM file showing %dx%d to be the last known dimensions */\n",m,n);
            printf("/* Locate and try reading the stored KY list file */\n");
            if((kyfile = fopen(kyfilenm, "r")) EQL NULL) 
            { 
                // SECTION B
            } 
            else 
            { 
                // SECTION B'
                if(m>0&&n>0)
                {
                    // SECTION C
                }
                fclose(kyfile);
            }
    
            fclose(dimfile);
            puts("Type A New String and Press <ENTER> To Store in RAM and Binary File, ");
    
            for(m=lastknown_rows,n=lastknown_cols;;m++,n++)
            {
                if((dimfile = fopen(dimfilenm, "w")) NEQL NULL)
                {                    
                    // SECTION D
                    } else { /* if(buff<MAX_INPUT_LEN) */
                        printf("/* Oops! Your input is too large. Keep it below 254 characters */\n");
                    }                        
                }  else printf("/* Oops! Cannot open DIM file for updates */\n");
                fclose(dimfile);
            }
        }
         else 
        {
            // SECTION A'
        }

  6. #6
    pwning noobs Zlatko's Avatar
    Join Date
    Jun 2009
    Location
    The Great White North
    Posts
    132
    Edit:
    Last edited by Zlatko; 07-02-2009 at 10:51 AM. Reason: misunderstanding

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by deendee View Post
    Hi Matsp. Much appreciated your quick rescue response. Thanks man, you were first.

    Concerning...
    Debugger? Yes, I have tried the VS 2003 Debugger, Intel C++ Debugger and WinDbg to no much avail.
    Well, I'm not entirely sure what you have done with a debugger, but in my experience, this type of error is EASY to find. Just reproduce the problem in the debugger, and look at the call-stack.
    [quopte]
    I agree with you though for pointing out quite possibly where the bug might be coming from - some NULL pointer somewhere, or some NULL misuse. If that be so, I have gotten there for following 'sound' advice all over the net as to how 'best' to free heap'd memory by NULLing the pointer after free'ing it. I probably have abused otherwise good practice. I'll check out for my error.

    Concering...
    Code:
    #define EQL == /* Equal To */
    #define NEQL != /* Not Equal To */
    #define LOEQL <= /* Less Than or Equal To */
    #define GOEQL >= /* Greater Than or Equal To */
    ...I must say, in my humble opinion, this has saved me a lot of times in avoiding major typos bugs, like assignments (=) when I needed comparison (==), for instance. This approach, is actually well recommended in books like Deep C. So I type...

    [/quote]
    I don't agree. Yes, it happens that mistakes with single equal instead of double equal is used. Enabling high warning levels generally shows these things up in most compilers. And I have never actually seen that sort of thing in any commercial code that I have worked with. The source code for the system I'm working with at the moment is about 30 million lines all in (the group I work in is about a million or so lines of code in itself). If there is such a thing in any of that code, I certainly have yet to see that bit of code.

    You are pretty much making your own private version of the language C, which only you understand.


    Finally, I tried to compile your code and run it on my machine. It works so far. However, I have no idea what the input files you have are like, so I probably aren't doing the right things to reproduce the problem.

    I found another few things that don't really look right: after fread() from kbfile, it says "Error writing to file" - which is clearly not right!

    This won't work right:
    Code:
    					gets(buff);
    					inputlen=(strlen(buff)+1);
    					if(inputlen<MAX_INPUT_LEN)
    gets will happily accept a name that is MUCH larger than MAX_INPUT_LEN - and what happens then? You may be able to detect it, but it may also crash the program then and there - depends on what gets overwritten. Checking it is a bit like aiming and trying to fire at your foot with a gun to see if it's loaded. If it's not, you don't get shot in the foot - good. But if it is, then your foot is shot to pieces - not a good plan, do you think? gets() is one of those functions that shouldn't have been invented in the first place, or at the very least, removed once it was discovered how bad it is....

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Jul 2009
    Posts
    3

    I fixed your bug!

    Deendee, I fixed the bug in your code. You owe me some beer!

  9. #9
    Registered User
    Join Date
    Feb 2009
    Posts
    278
    I just had to say that I loved the "shooting yourself in the foot" analogy

  10. #10
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Smile I The Bug Myself 3 Days Ago!!!

    Thanks dude for following thru.

    I found out what was wrong with my code myself, only I didn't publish soon enough. The bug was in the looping of malloc (after the realloc) without first initializing the looped pointer kbmtx[i]. So I fixed that by just initializing the pointer to a NULL; That fixed my mock-code and the production app-code is running great now.

    All the other commissions and/or omissions pointed out before, have been considered and action taken - where necessary. Like I said before, the production code is far cleaner and neater than this concept test code published above.

    I thank God and all who helped me think hard. Let's keep c'ing on this forum and keep this lang going, it gives power to the programmer - and yes you can shoot urself in the foot too!

    But I still like it, much!

    Cheers!

  11. #11
    Registered User
    Join Date
    Jul 2009
    Posts
    4

    Thumbs up I Fixed The Bug Myself 3 Days Ago!!!

    |;-)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help to fix code
    By anik18 in forum C Programming
    Replies: 19
    Last Post: 05-29-2009, 06:06 AM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. Replies: 1
    Last Post: 05-26-2006, 08:13 AM
  4. Updated sound engine code
    By VirtualAce in forum Game Programming
    Replies: 8
    Last Post: 11-18-2004, 12:38 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM