Thread: malloc, iterations, bus error and more

  1. #1
    Registered User
    Join Date
    Nov 2009
    Posts
    9

    malloc, iterations, bus error and more

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main(int argc, char* argv [])
    {
    	FILE        *input;
    	double      valid1, valid_input, b, tmp, *x, *fx, *dx, area, total_area;
    	int         rec, ns, i, curr_col, col;
    	
    	input = fopen("px270prog3a.dat", "r");
    	
    	if(argc != 2)
         {
            printf("Please enter one argument.\n");
            exit(EXIT_FAILURE);
         }
         else
         {
    		valid1=sscanf(argv[1], "%f", &b);
    		
    		valid_input = (valid1 != 0) && (valid1 != EOF) && (b <= (M_PI / 2));
            
    		if(!valid_input)
            {
               printf("Invalid input, please enter a value between 0 and Pi/2.\n");
               exit(EXIT_FAILURE);
    		}
    		
    		if(input == (FILE*) NULL) 
    		{
    			printf("Could not open input file\n");
    		}
    				
    		    
    		ns = 0;
    		while(fscanf(input,"%f",&tmp) == 1) ns++;
    		ns = ns / 2;
    	
    		
    		x = (double*) malloc((ns+1)*sizeof(double));
    		fx = (double*) malloc((ns+1)*sizeof(double));
    		printf("Allocated memory for %d records\n",ns+1);
    
    		rewind(input);
    		i=0; rec = 0;
    		while(fscanf(input,"%lf",&tmp) == 1)
    		{
    			curr_col = (rec % 2);
    			if(curr_col==1)
    			{
    				fx[i] = (double)(tmp);
    			}
    			else if(curr_col==col)
    			{
    				x[i] = (double)(tmp);
    				i++;
    			}
    			rec++;
    		}
    		
    		x[0] = 0;
    		dx[0] = 0;
    		fx[0] = 1;
    		i = 1;
    		area = 0;
    		total_area = 0;
    		
    		while(i < (b * 20000 / M_PI))
    		{
    			dx[i] =  x[i] * x[i-1];
    			i++;
    		}
    		
    		while(i < (b * 20000 / M_PI))
    		{
    			area = fx[i-1] * dx[i];
    			total_area = total_area + area;
    			i++;
    		}
    		
    		printf("Area under the curve is %f \n", total_area);
    		return(0);
    	}
    }
    I've been given an assignment to find the area under a cos^2(x) curve. The input file consists of 10000 values in each of 2 collumns, the first collumn is the value of x and the second collumn is the value of the function at that point.

    I then have to find the area under the curve (between 0 and the point b which must be less than pi/2) using the following function:

    (sum of) (f(xi) * ((xi) - (x(i-1)) between i=1 and i=b (the i's are supposed to be subscript).

    Anyway, the code is how far I've got so far, it compiles but it gives the total area to be 0 unless b is 0.97 or higher, in which case it says "bus error".

    Any advice you can offer will be greatly appreciated.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    1. valid1 can never equal EOF, because it's a double, not an int.
    2. You don't need to typecast NULL when you compare it to your file handle (or ever for that matter).
    3. You should probably stop compiling as C++, or at least stop typecasting malloc.
    4. tmp is already a double, so why are you typecasting it to a double again?
    5. You immediately overwrite the first value of x[0] and fx[0], any reason?
    6. You should be doing: while( i < ns ) to control your loops. Not while( i < (some other number) ). (Or half ns, since you seem to have split it across x and fx.)


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Nov 2009
    Posts
    9
    Quote Originally Posted by quzah View Post
    1. valid1 can never equal EOF, because it's a double, not an int.
    2. You don't need to typecast NULL when you compare it to your file handle (or ever for that matter).
    3. You should probably stop compiling as C++, or at least stop typecasting malloc.
    4. tmp is already a double, so why are you typecasting it to a double again?
    5. You immediately overwrite the first value of x[0] and fx[0], any reason?
    6. You should be doing: while( i < ns ) to control your loops. Not while( i < (some other number) ). (Or half ns, since you seem to have split it across x and fx.)
    Quzah.
    In response to points 1 and 2, is leaving them as they are going to be detrimental to the function of my program (I'd rather make it look neat afterwards if it isn't going to break my program).
    3 - What do you mean? The module I'm studying is 'C programming' so I'm not allowed to use any different language. Also, what did you mean about typecasting malloc, one of the objectives of the assignment was to use the malloc function.
    4 - What does typecasting mean? I didn't realise I'd done it twice anyway.
    5 - I define x[0] and fx[0] to be 0 and then the value that I wish to use in the calculation is found by overwriting it until a value depending on b is found.
    6 - Also, I want to stop the loop when i = b rather than it going all the way to the end of the file which is why I dont use ns.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    1 & 2 - It won't keep your program from running, it's just not entirely accurate.
    3 - If you are getting warnings or errors on those lines if you remove the typecast, then you are compiling as C++, or you haven't included the correct header.
    4 - Typecasting is this: int x = (int) 5.6; -- basically it's forcing a value to be another type, in this case, we are telling it to treat 5.6 as an int.
    6 - The problem with looping on some value other than ns, is that you only have ns elements. If you go more than that, you run out of allocated space, which is bad.
    Code:
    #define NS 5
    int x[ NS ];
    int y;
    
    for( y = 0; y < 10000; y++ )
    {
        if( y < NS )
        {
            printf( "Ok to access." );
            x[ y ] = 1;
        }
        else
        {
            printf( "Please crash my system!" );
            x[ y ] = DIEDIEDIE;
        }
    Basically, if you aren't using ns, since that's the actual size or number of elements you have, you risk running off to where you shouldn't, as illustrated.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Nov 2009
    Posts
    9
    OK, but at the start I said that b must be smaller than pi/2. If you look at that surely b cannot exceed ns? Also, I tried swapping the code around so i have (i < ns) and got a segmentation fault, what does that mean? :S

    Sorry if these questions seem obvious, I'm very new to programming.

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by z0diark View Post
    OK, but at the start I said that b must be smaller than pi/2. If you look at that surely b cannot exceed ns
    Well, let's say b is 1/2 pi. That means b is about 1.5, right?
    Code:
    while(i < (b * 20000 / M_PI))
    What is:

    1.5 * 20000 / 3.14 ? (Hint: About 10,000.)

    Your loop is going to loop about 10000 times. Did you allocate 5000 spaces for each x and fx?


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    Nov 2009
    Posts
    9
    Quote Originally Posted by quzah View Post
    Well, let's say b is 1/2 pi. That means b is about 1.5, right?
    Code:
    while(i < (b * 20000 / M_PI))
    What is:

    1.5 * 20000 / 3.14 ? (Hint: About 10,000.)

    Your loop is going to loop about 10000 times. Did you allocate 5000 spaces for each x and fx?
    Quzah.
    Yes, I know it's going to loop 10000 times if b is pi/2. There are 10000 rows in my .dat file for x and fx as x increases from 0 to pi/2. Also, since there are 10000 rows and 2 collumns (20000 elements in the entire array) should I say 1.5 * 40000 /M_PI instead?

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Why don't you make a small test case, instead of a huge program? Consider:
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    
    int main( void )
    {
        FILE *fp;
        fp = fopen( "yourfile.dat", "r" );
        if( fp )
        {
            double *array = NULL;
    
            array = malloc( 100 * sizeof *array );
            if( array )
            {
                double num = 0, sum = 0;
                size_t x;
                for( x = 0; x < 100; x++ )
                    if( fscanf( fp, "%lf", &num ) == 1 )
                    {
                        sum += num;
                        printf( "got %f as num, sum is %f\n", num, sum );
                    }
    
                free( array );
            }
    
            fclose( fp );
        }
        return 0;
    }
    Now throw 100 numbers in a file. If it works fine, you're all set. Expand it. Basically, it's good to start small.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Nov 2009
    Posts
    9
    Ok I'll try it out with a smaller input file, does anyone else see anything wrong with my code?

Popular pages Recent additions subscribe to a feed