Why is my code resulting in a segmentation fault? - c

The tasks are the following:
/* LAB 6 TASK A*/
/*
Save the entire array ia into a file called 'filename' in a binary
file format that can be loaded by intarr_load_binary(). Returns
zero on success, or a non-zero error code on failure. Arrays of
length 0 should produce an output file containing an empty array.
*/
/* LAB 6 TASK B*/
/*
Load a new array from the file called 'filename', that was
previously saved using intarr_save_binary(). Returns a pointer to a
newly-allocated intarr_t on success, or NULL on failure.
*/
For A, my code is the following:
int intarr_save_binary( intarr_t* ia, const char* filename )
{
int returnValue = 0;
unsigned int len = ia->len;
FILE *f;
if( NULL == (f = fopen (filename, "wb") ))
{
perror( "fopen failed" );
returnValue = 1;
}
else if ( fwrite ( &len, sizeof(int), 1, f) == 1 )
{ // then write of length successful
if (fwrite (ia->data, sizeof(int), len, f) == len)
{
returnValue = 0; // indicate success
}
else
{ // else, write of data failed
returnValue = 3;
}
}
else
{ // else, failed to write len value to file
returnValue = 4;
}
fclose( f ); // cleanup (writes last buffer to file)
return( returnValue );
}
And for B, my code is the following:
intarr_t* intarr_load_binary( const char* filename )
{
unsigned int len = 0;
FILE *f = NULL;
intarr_t* newia = NULL;
if( NULL == fopen (filename, "rb") )
{ // then, fopen failed
perror( "fopen failed" );
exit( EXIT_FAILURE );
} // end if
// implied else, fopen successful
if( NULL == (newia = malloc (sizeof(intarr_t)))){
perror( "malloc failed" );
fclose(f);
exit( EXIT_FAILURE );
} // end if
// implied else, malloc successful
if( (fread (&len, sizeof(int), 1, f) != 1 ) )
{ // then fread failed
perror( "fread failed" );
fclose(f);
free( newia );
exit( EXIT_FAILURE );
} // end if
// implied else, fread for len successful
newia->len = len;
if( NULL == (newia->data = malloc (len*sizeof(int)) ) )
{ // then malloc failed
perror( "malloc failed" );
fclose(f);
free( newia );
exit( EXIT_FAILURE );
} // end if
// implied else, malloc successful
if( fread( newia->data, sizeof(int), len, f ) != len )
{ // then, fread failed
perror( "fread failed" );
fclose(f);
free(newia->data);
free(newia);
exit( EXIT_FAILURE );
} // end if
// implied else, fread successful
fclose (f);
return newia;
} // end function: intarr_load_binary
Can anyone please tell me why my code results in a segmentation fault? Thank you very much.

In the code for B, NULL is passed to fread() in the line
if( (fread (&len, sizeof(int), 1, f) != 1 ) )
so it may lead to Segmentation Fault.
To fix this, assign the file pointer returned from fopen() to f:
Change
if( NULL == fopen (filename, "rb") )
to
if( NULL == (f = fopen (filename, "rb")) )
Also check if the parameters passed to the functions are valid.

Related

Read character by character from a file and put each line in a String

I've to read character by character from a file and put each line in a String.
The problem is that i don't know the size of each line so eventually I've to reallocate the memory. So If I try a reallocation my program return error. Am I doing something wrong?
FILE * file = fopen(input,"r");
if(file != NULL){
char temp;
char * line;
line = (char *) malloc(sizeof(char) * 10);
int i = 0;
while((temp = fgetc(file)) != EOF){
if(temp == '\n'){
i = 0;
}
else{
if(i > strlen(line) - 2){
line = (char *) realloc(line,sizeof(line) * 10);
}
line[i] = (char) temp;
i++;
}
}
free(line);
fclose(file);
}
else{
}
the following proposed code:
cleanly compiles
performs the desired functionality
properly checks for errors
outputs user error messages to stderr
outputs the text reason the system thinks an error occurred to stderr
documents why each header file is included
shows an example of how to handle the case where the user failed to enter a command line parameter (in this case a input file name)
makes use of size_t rather than int when passing parameters to malloc() and realloc()
and now, the proposed code:
#include <stdio.h> // fopen(), perror(), fclose() fprintf()
#include <stdlib.h> // exit(), EXIT_FAILURE, malloc(), realloc(). free()
int main( int argc, char *argv[] )
{
if( argc != 2 )
{
fprintf( stderr, "USAGE: %s <fileName>\n", argv[0] );
exit( EXIT_FAILURE );
}
FILE * file = fopen( argv[1], "r" );
if( !file )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
int ch;
char * line = malloc( 10 );
if( !line )
{
perror( "malloc failed" );
fclose( file ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, malloc successful
size_t lineLen = 10;
size_t i = 0;
while( (ch = fgetc(file)) != EOF )
{
if( ch == '\n' )
{
line[i] = '\0';
// do something with contents of line
i = 0;
}
else
{
if(i >= lineLen )
{
lineLen *= 2;
char * temp = realloc( line, lineLen );
if( !temp )
{
perror( "realloc failed" );
// cleanup
fclose( file );
free( line );
exit( EXIT_FAILURE );
}
line = temp;
}
line[i] = (char)ch;
i++;
}
}
free(line);
fclose(file);
}

Error when I try to open a .dat file

I have a problem when I try to open a .dat file in a c code. Probably the error I made will be very obvious to some of you but I can't find it so I ask for your help.
The point of my code is to open the .dat file which contains 12.000.000 double numbers and store it in a cuDoubleComplex array which size will be 6.000.000 variables (the even variables of the .dat represents the real part and the odd variables the imaginary (I mean the order, not the value of the variable))
Here is an extract of my code:
#include "cuComplex.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main(void)
{
int n = 12000000; //12.000.000
int lse = n / 2;
double *data = (double *)malloc(12000000 * sizeof(double));
double *data2 = (double *)malloc(12000000 * sizeof(double));
FILE *f, *f2;
cuDoubleComplex *se, *se2;
f = fopen("ref_PRI20.dat", "r");
fread(data, sizeof(double), n, f);
fclose(f);
f2 = fopen("surv_PRI20.dat", "r");
fread(data2, sizeof(double), n, f2);
fclose(f2);
for (int a = 0; a < n; a++)
{
printf("%f\n", data2[a]);
}
se = (cuDoubleComplex*)malloc(lse * sizeof(cuDoubleComplex));
se2 = (cuDoubleComplex*)malloc(lse * sizeof(cuDoubleComplex));
for (int a = 0; a<n / 2; a++)
{
se[a].x = data[2 * a];
se[a].y = data[2 * a + 1];
se2[a].x = data2[2 * a];
se2[a].y = data2[2 * a + 1];
}
free(data);
free(data2);
}
I have added the printf lines and bucle just to check and all I get is "0,0000" as a value. Although when I continue with the programm the se and se2 arrays seems to get random values.
I know the size of the arrays is huge but I need to work with that amount of data.
I also have tried to work in matlab and I had no mistakes in there. This is the code that I used in matlab and everything was fine so I guess there is no problem with the .dat files but only with my code.
f = fopen ("ref_PRI20.dat", 'r');
Data = fread (f, 12e6, 'double');
fclose (f);
dat=(Data(1:2:end)+1i*Data(2:2:end)).';
Here's a scan of the input data so you can see the format. I hope it will help.
enter image description here
Any help will be appreciated.
No error checking on the original code for malloc or fopen.
Since a comment said the file was opened in a text reader and had commas between values, fscanf should be used to input the values instead of fread.
Since the values must be scanned one at a time there isn't a need for the data or data2 pointers.
Could not compile this as I don't have cuComplex.h
#include "cuComplex.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main(void)
{
int n = 12000000; //12.000.000
int lse = n / 2;
FILE *f, *f2;
cuDoubleComplex *se, *se2;
f = fopen("ref_PRI20.dat", "r");
f2 = fopen("surv_PRI20.dat", "r");
se = malloc(lse * sizeof(cuDoubleComplex));
se2 = malloc(lse * sizeof(cuDoubleComplex));
for (int a = 0; a < lse; a++)
{
if ( 1 != fscanf ( f, "%lf ,", &se[a * 2].x])) {
fprintf ( stderr, "could not scan double\n");
break;
}
if ( 1 != fscanf ( f, "%lf ,", &se[a * 2 + 1].y)) {
fprintf ( stderr, "could not scan double\n");
break;
}
if ( 1 != fscanf ( f2, "%lf ,", &se2[a * 2].x)) {
fprintf ( stderr, "could not scan double\n");
break;
}
if ( 1 != fscanf ( f2, "%lf ,", &se2[a * 2 + 1].y)) {
fprintf ( stderr, "could not scan double\n");
break;
}
}
fclose(f);
fclose(f2);
free ( se);
free ( se2);
return 0;
}
the following proposed code:
cleanly compiles
properly checks for and handles errors
reads the data directly into the struct.
Did not use the cuComplex.h file as that was not available.
avoided the use of 'magic' numbers
although the 'b' is not necessary in linux/unix, properly set the open mode to BINARY READ
documented why each header file is included.
eliminated all unnecessary variables and unnecessary calls to malloc()
eliminated all unnecessary data copying.
It may be desirable to read the data in a loop, using a 'moving window' until a 12000000 doubles are read. I'll let you add that feature, if necessary.
And now the proposed code:
#include <stdio.h> // fopen(), fread(), printf(), fprintf(), perror()
#include <stdlib.h> // exit(), EXIT_FAILURE, malloc(), free()
#define N 12000000
struct cuDoubleComplex
{
double x;
double y;
};
int main(void)
{
struct cuDoubleComplex *data = malloc( (N>>1) * sizeof(double));
if( !data )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
struct cuDoubleComplex *data2 = malloc( (N>>1) * sizeof(double));
if( !data2 )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
FILE *f = fopen("ref_PRI20.dat", "rb");
if( !f )
{
perror( "fopen failed" );
free( data );
free( data2 );
exit( EXIT_FAILURE );
}
size_t nmemb = fread(data, sizeof(double), N, f);
if( nmemb != N )
{
fprintf( stderr, "read of first file only read %lu doubles\n", nmemb );
free( data );
free( data2 );
fclose( f );
exit( EXIT_FAILURE );
}
fclose(f);
FILE *f2 = fopen("surv_PRI20.dat", "rb");
if( !f2 )
{
perror( "fopen failed" );
free( data );
free( data2 );
exit( EXIT_FAILURE );
}
size_t nmemb2 = fread(data2, sizeof(double), N, f2);
if( nmemb2 != N )
{
fprintf( stderr, "read of second file only read %lu doubles\n", nmemb2 );
free( data );
free( data2 );
fclose( f2 );
exit( EXIT_FAILURE );
}
fclose(f2);
for (int a = 0; a < N; a++)
{
printf("%f\n", data2[a].y);
}
free(data);
free(data2);
} // end function: main

runtime error with malloc

#define MAXL 256
I think the problem with my code is that eventho numInput = 3, somehow, output[2] did not exist so that when I try to assign it, the program crash (just guessing).
Is there a way to check if ouput[2] exist? or maybe someone will be able to find out the real problem of my code, that would be awesome!
Any help would be greatly appreciated!
NOTE: The reason that I cast malloc is that it is expected by my lecturer.
Input strings are: 25 7 * 14 - 6 +
1 24 3 + * 41 -
2 37 4 + * 15 +
void processPostfixExp(const char * fileName)
{
char ** input = NULL;
double ** output = NULL;
int i = 0, numInput = 0;
char tempInput[MAXL] = {0};
FILE * pFile = NULL;
/* Get number of strings, check if file is readable and open file */
numInput = checkFile(fileName);
pFile = fopen(fileName, "r");
/* Allocate memory for the string storages and alert if fail */
input = (char**)malloc(numInput * sizeof(char*));
output = (double**)malloc(numInput * sizeof(double*));
if(!input || !output)
{
printf("Memory allocation failed.\n");
system("PAUSE");
exit(1);
}
/* Scan the file by lines and duplicate the string to input storage */
for(i = 0; i < numInput; ++i)
{
fgets(tempInput, MAXL, pFile);
tempInput[strlen(tempInput)-1] = '\0';
input[i] = strdup(tempInput);
//printf("\n%s", input[i]);
}
/* Close file and clear screen */
fclose(pFile);
system("CLS");
/* Call converter and display result */
printf("-------------------------------------------------------\n");
printf("\nPostfix expression evaluation:\n");
for(i = 0; i < numInput; ++i)
{
printf("input = %s", input[i]); /* i = 2 Printf SUCCESS */
*output[i] = evaluatePost(input[i]); /* i = 2 CRASH HERE */
/* I added a check at the top most of the evaluatePost(), program did not get to there */
//printf("\nCase %d: %s\nResult:%.2f\n", i + 1, input[i], *output[i]);
}
printf("\n");
printf("-------------------------------------------------------\n");
}
UPDATE:
so I added these lines and can confirm that output[2] does not exist... how is that possible? Please help, Thank you!
for(i = 0; i < numInput; ++i)
{
*output[i] = (double)i;
printf("output[%d] = %.1f\n", i, *output[i]);
}
The problem is that you have:
*output[i]
You have allocated numInput pointers to double, but the pointers themselves don't exist.
It looks like you want to allocate space not for pointers, but for doubles:
double *output;
…
output = (double*)malloc(numInput * sizeof(double));
I'm not sure what is wrong with your call to evaluatePost(), especially as you have not provided a prototype for that function.
However, overall, your code should look similar to the following:
in the future, please post code that (standalone) actually cleanly compiles
when you want help with a run time problem.
strongly suggest compiling with all warnings enabled.
For gcc, at a minimum, use '-Wall -Wextra -pedantic'
When handling a error, always cleanup allocated memory, open files, etc.
#define _POSIX_C_SOURCE (200809L)
#include <stdio.h>
#include <stdlib.h> // exit() and EXIT_FAILURE
#include <string.h> // memset() and strdup()
#define MAXL (256)
// prototypes
int checkFile( const char * );
double evaluatePost( char * );
void processPostfixExp(const char * fileName)
{
char **input = NULL;
double **output = NULL;
int i = 0;
int numInput = 0;
char tempInput[MAXL] = {0};
FILE *pFile = NULL;
/* Get number of strings, check if file is readable and open file */
numInput = checkFile(fileName);
if( NULL == (pFile = fopen(fileName, "r") ) )
{ // then fopen failed
perror( "fopen for input file failed" );
exit( EXIT_FAILURE );
}
/* Allocate memory for the string storages and alert if fail */
if( NULL == (input = malloc(numInput * sizeof(char*)) ) )
{ // then malloc failed
perror( "malloc for input failed" );
fclose( pFile );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
memset( input, 0x00, numInput*sizeof(char*) ); // to make later free() operation easy
if( NULL == (output = malloc(numInput * sizeof(double*)) ) )
{ // then malloc failed
perror( "malloc for output failed" );
fclose( pFile );
free( input );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
memset( output, 0x00, numInput * sizeof(double*) ); // to make later free() operation easy
/* Scan the file by lines and duplicate the string to input storage */
for(i = 0; i < numInput; ++i)
{
if( NULL == fgets(tempInput, MAXL, pFile) )
{ // then fgets failed
perror( "fgets for input file failed" );
fclose( pFile );
for( int j=0; j<numInput; j++ )
{
free( input[j] );
free( output[j] );
}
free( input );
free( output );
exit( EXIT_FAILURE );
}
// implied else, fgets successful
char * offset = NULL;
if( NULL != (offset = strstr( tempInput, "\n" )) )
{ // then newline found
*offset = '\0';
}
if( NULL == (input[i] = strdup(tempInput) ) )
{ // then strdup failed
perror( "strdup for input line failed" );
fclose( pFile );
for( int j=0; j<numInput; j++ )
{
free( input[j] );
free( output[j] );
}
free( input );
free( output );
exit( EXIT_FAILURE );
}
//printf("\n%s", input[i]);
} // end for
/* Close file and clear screen */
fclose(pFile);
system("CLS");
/* Call converter and display result */
printf("-------------------------------------------------------\n");
printf("\nPostfix expression evaluation:\n");
for(i = 0; i < numInput; ++i)
{
printf("input = %s", input[i]); /* i = 2 Printf SUCCESS */
*output[i] = evaluatePost(input[i]); /* i = 2 CRASH HERE */
/* I added a check at the top most of the evaluatePost(), program did not get to there */
//printf("\nCase %d: %s\nResult:%.2f\n", i + 1, input[i], *output[i]);
}
printf("\n");
printf("-------------------------------------------------------\n");
for( int j=0; j<numInput; j++ )
{
free( input[j] );
free( output[j] );
}
free( input );
free( output );
} // end function: processPostfixExp

Getting abort trap 6 after malloc() call

I'm new to C from java and having a bit of trouble with memory management. I have this function whose purpose is to read x through y lines of a file. I am trying to write the function so that it can handle any size line in a file. Here is the function:
char** getRangeOfLinesFromFile(char* fileName, int startingLineNumber, int endingLineNumber, int BUFFER_SIZE) {
//set up an array to hold the range of lines we're going to return
//+1 because the range is inclusive
char** lineArray = malloc((endingLineNumber - startingLineNumber + 1) * sizeof(char*));
//get the file
FILE* file_ptr = fopen(fileName,"r");
//our buffer array will hold the lines as we read them
char *buffer = (char*) malloc(sizeof(char) * BUFFER_SIZE);
//this array will be used just in case a line is bigger than our buffer and we need to take multiple passes at it
char *temp = (char*) malloc(sizeof(char) * BUFFER_SIZE);
int lineCounter = 1;
while (fgets(buffer, BUFFER_SIZE, file_ptr) != NULL) {
strcat(temp, buffer);
size_t len = strlen(temp);
if (temp[len - 1] != '\n') {
realloc(temp,BUFFER_SIZE);
} else {
if (shouldKeepLine(lineCounter,startingLineNumber,endingLineNumber)) {
int index = lineCounter - startingLineNumber;
lineArray[index] = malloc(len * sizeof(char));
//ERROR HERE
strcpy(lineArray[index],temp);
}
*temp = *(char*) malloc(sizeof(char) * BUFFER_SIZE);
lineCounter++;
// we don't need to keep reading the file if we're not going to print anything else
if (lineCounter > endingLineNumber) {
break;
}
}
}
//clean up
free(buffer);
free(temp);
fclose(file_ptr);
return lineArray;
}
This is what the shouldKeepLine() function looks like:
bool shouldKeepLine(int lineNumber, int lowerBound, int upperBound) {
if (lineNumber >= lowerBound && lineNumber <= upperBound) {
return true;
}
return false;
}
During testing I'm using a Buffer Size of 10, so I can test that it 'grows' properly. This size will increase when the program is complete. The test file I'm using to read from currently has 2 lines. The first line of the file has like 15 characters. The second line has around 90 or so.
When I run this program, I get an Abort trap 6 error. After putting some debugging print statements in, I see that it throws that error on the strcpy call right below the ERROR HERE comment in my code, but only for line 2, not line 1. Line 1 is also larger than the buffer but a tenth or so the size of line 2. If I change this line:
lineArray[index] = malloc(len * sizeof(char));
to:
lineArray[index] = malloc(len * sizeof(char) * 1000);
It works fine. This just doesn't seem dynamic.
Not sure what I'm doing wrong. Any help is appreciated.
the following code should (not compiled/tested)
perform the activity you want to implement
char** getRangeOfLinesFromFile(
char* fileName,
int startingLineNumber, // note: first line in file is considered line 1, not 0
int endingLineNumber,
int BUFFER_SIZE )
{
//set up an array to hold the range of lines we're going to return
//+1 because the range is inclusive
char** lineArray = NULL;
// what about if endingLineNumber is < startingLine Number???
int lineCount = endingLineNumber - startingLineNumber + 1;
int i; // loop counter/index
// get array of pointers to point to each line that is kept
if( NULL == (lineArray = malloc( (lineCount) * sizeof(char*)) ) )
{ // then, malloc failed
perror( "malloc for array of pointers failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
// *I* would use the getline()) function, so the length of the
// input line would not matter.
// however, the following code uses the passed in value BUFFER_SIZE
// (which I would have made a #define and not passed it in)
// initialize the array of pointers to char
for( i=0; i<lineCount; i++)
{
if( NULL == (lineArray[i] = malloc(BUFFER_SIZE) ) )
{ // then malloc failed
perror( "malloc for each line storage area failed" );
// free all allocated memory
// suggest using the cleanup() function, below
exit( EXIT_FAILURE );
}
// implied else, malloc successful
// (optional, but good practice)
// clear each memory allocated area to NUL bytes
memset( lineArray[i], 0x00, BUFFER_SIZE );
} // end for
// if got here, then all memory allocations are completed
//get the file
FILE* file_ptr = NULL;
if( NULL == (file_ptr = fopen(fileName,"r") ) )
{ // then, fopen failed
perror( "fopen for input file failed" );
// free all allocated memory
// suggest using the cleanup() function, below
exit( EXIT_FAILURE );
}
// implied else, fopen successful
for(i=0; i < (startingLineNumber-1); i++)
{
unsigned int inputChar;
while( (inputChar = fgetc( file_ptr )) != EOF
{
if( EOF == inputChar )
{ // then, file does not contain nearly enough lines
// free all allocated memory
// suggest using cleanup() function, below
fclose( file_ptr );
return (NULL);
}
if( '\n' == inputChar ) { break;} // end of current line
} // end while
} // end for
// if got here, then ready to read first line of interest
// NOTE: be sure there is a newline at end of input file
int bufLength = BUFFER_SIZE;
for( i=0; i<lineCount; i++ )
{
// get a line, allowing for max input buffer length
if( fgets( &lineArray[i][strlen(lineArray[i])], BUFFER_SIZE, file_ptr ) )
{ // then got (more) line, up to BUFFER_SIZE -1
if( '\n' != lineArray[i][(strlen( lineArray[i] )-1) )
{ // then more char available for this line
char *tempPtr = NULL;
if( NULL == (tempPtr = realloc( lineArray[i], (bufLength*2) ) ) )
{ // then, realloc failed
perror( "realloc to increase buffer size failed" );
// add --free all the allocations--
// suggest sub function with passed parameters
fclose( file_ptr );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
// update the pointer in the array
lineArray[i] = tempPtr;
// update buffer length indication
bufLength *= 2;
i--; // so will append to same entry in array for rest of line
}
else
{ // else, got all of line
bufLength = BUFFER_SIZE; // reset
} // end if
}
else
{ // else, fgets failed
perror( "fgets for line failed" );
// add --free all allocations--
// suggest sub function with passed parameters
fclose( file_ptr );
exit( EXIT_FAILURE );
} // end if
} // end for
// if got here, then all desired lines read successfully
fclose( file_ptr );
return lineArray;
} // end function: getRangeOfLinesFromFile
remember that the caller has to free all those memory allocations
first the allocation for each line
then the allocation for the lineArray
perhaps like this:
void cleanup( char**pArray, int entryCount )
{
int i; // loop counter/index
for( i=0; i<entryCount; i++ )
{
free(pArray[i]);
}
free(pArray);
} // end function: cleanup
This line of code is likely to be troublesome:
strcat (temp, buffer);
At the point it executes, temp has been malloced, but not initialized.
There really ought to be checks after every malloc() to make sure they succeeded.

Loading data from a file to an array in c

I want to load an array from a file that I previously saved. I ran the code below, but for some reason, when I loaded the array, the array length that I loaded was not the same as the length of the array that I had saved. How would I change the length for my load a file code so that it would work for any array length?
intarr_t* intarr_load_binary( const char* filename )
{
unsigned int len = 0;
FILE *f = fopen (filename, "rb");
fscanf (f, "%d", len);
intarr_t* newia = malloc (sizeof(intarr_t));
assert (newia);
newia->data = malloc (len*sizeof(int));
assert(newia->data);
newia->len = len;
if (f != NULL)
{
while (!feof(f))
{
fscanf (f, "%d", newia->data);
}
}
else
{
return NULL;
}
fclose (f);
return newia;
}
The struct that I used for the save/load is here:
typedef struct {
int* data;
unsigned int len;
} intarr_t;
The code that I used to save the file is here:
int intarr_save_binary( intarr_t* ia, const char* filename )
{
unsigned int len = ia->len;
FILE *f;
f = fopen (filename, "wb");
if (fwrite (ia->data, sizeof(int), len, f) == len)
{
return 0;
}
else
{
return 1;
}
fclose (f);
}
the code is writing no length (len) value as the first data item to the file
yet the code is reading a length (len) value
as if it were the first data item in the file.
this code is full of errors and oversights:
int intarr_save_binary( intarr_t* ia, const char* filename )
{
unsigned int len = ia->len;
FILE *f;
f = fopen (filename, "wb");
if (fwrite (ia->data, sizeof(int), len, f) == len)
{
return 0;
}
else
{
return 1;
}
fclose (f);
}
suggest using code similar to this:
int intarr_save_binary( intarr_t* ia, const char* filename )
{
int returnValue = 0;
unsigned int len = ia->len;
FILE *f;
if( NULL == (f = fopen (filename, "wb") )
{
perror( "fopen failed" );
returnValue = 1;
}
else if ( fwrite ( &len, sizeof(int), 1, f) == 1 )
{ // then write of length successful
if (fwrite (ia->data, sizeof(int), len, f) == len)
{
returnValue = 0; // indicate success
}
else
{ // else, write of data failed
returnValue = 3;
}
}
else
{ // else, failed to write len value to file
returnValue = 4;
}
fclose( f ); // cleanup (writes last buffer to file)
return( returnValue );
} // end function: intarr_save_binary
this code needs some work.
for instance because assert should not enabled in production code
and error conditions not being checked
and cleanup not being properly performed
if the program is ok to continue after an I/O error
by always returning NULL
then you could change the following,
to return NULL rather than exiting the program
intarr_t* intarr_load_binary( const char* filename )
{
unsigned int len = 0;
FILE *f = fopen (filename, "rb");
fscanf (f, "%d", len);
intarr_t* newia = malloc (sizeof(intarr_t));
assert (newia);
newia->data = malloc (len*sizeof(int));
assert(newia->data);
newia->len = len;
if (f != NULL)
{
while (!feof(f))
{
fscanf (f, "%d", newia->data);
}
}
else
{
return NULL;
}
fclose (f);
return newia;
}
suggest:
intarr_t* intarr_load_binary( const char* filename )
{
unsigned int len = 0;
FILE *f = NULL;
intarr_t* newia = NULL;
if( NULL == fopen (filename, "rb") )
{ // then, fopen failed
perror( "fopen failed" );
exit( EXIT_FAILURE );
} // end if
// implied else, fopen successful
if( NULL == (newia = malloc (sizeof(intarr_t)) )
{ // then malloc failed
perror( "malloc failed" );
fclose(f);
exit( EXIT_FAILURE );
} // end if
// implied else, malloc successful
if( (fread (&len, sizeof(int), 1, f) != 1 ) )
{ // then fread failed
perror( "fread failed" );
fclose(f);
free( newia );
exit( EXIT_FAILURE );
} // end if
// implied else, fread for len successful
newis->len = len;
if( NULL == (newia->data = malloc (len*sizeof(int)) ) )
{ // then malloc failed
perror( "malloc failed" );
fclose(f);
free( newia );
exit( EXIT_FAILURE );
} // end if
// implied else, malloc successful
if( fread( newia->data, sizeof(int), len, f ) != len )
{ // then, fread failed
perror( "fread failed" );
fclose(f);
free(newia->data)l
free(newia);
exit( EXIT_FAILURE );
} // end if
// implied else, fread successful
fclose (f);
return newia;
} // end function: intarr_load_binary

Resources