I am very much wanting to catch up on my C programming skills, so I have started my own self-training program, attempting to reading files and inserting their contents into different data structures.
Here, I am wanting to use specifically a dynamically-allocated pointer array. I have already used getc()
successfully in another similar program, but instead through the use of a static array, so I would very much like to continue using the getc()
function here.
So in this new implementation, here, I am just trying to insert all characters from an input file into an array, which I allocated using malloc()
. After one character is read at a time, I am trying to resize this pointer array by the size of one character each time so that there is room for the next character on the next iteration. Then, afterwards, iterate [character by character] through the new pointer array and simply print out all the contents.
However, I am receiving segmentation faults, so maybe I am going about this a little wrong? I would appreciate very much any feedback.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main( int argc, char *argv[] )
{
FILE *filePointer;
int c, i;
char *input_arrayPointer;
input_arrayPointer = ( char* ) calloc ( 1, sizeof( char ) );
printf("%p\n", input_arrayPointer);
int filled_elements = 0;
filePointer = fopen( argv[1], "r" );
if ( argc > 2 )
{
printf( "\nIncorrect usage, please say...\nRunProgram *filename*\n\n" );
exit( 1 );
}
if ( filePointer != NULL )
{
while ( ( c = getc( filePointer ) ) != EOF )
{
// filled_elements, to start, is 0
*( input_arrayPointer + filled_elements ) = c;
filled_elements++;
input_arrayPointer = ( char* ) realloc ( input_arrayPointer, (filled_elements * sizeof( char ) ) );
}
}
fclose( filePointer );
for ( i = 0; i < filled_elements; i++, input_arrayPointer++ )
{
printf("%c", *( input_arrayPointer + filled_elements );
}
}
In
while ( ( c = getc( filePointer ) ) != EOF )
{
// filled_elements, to start, is 0
*( input_arrayPointer + filled_elements ) = c;
filled_elements++;
input_arrayPointer = ( char* ) realloc ( input_arrayPointer, (filled_elements * sizeof( char ) ) );
}
What happens at the very first iteration?
input_arrayPointer
is one byte bigfilled_elements
is 0input_arrayPointer
is writtenfilled_elements
is incrementedrealloc
is called for filled_elements
bytes... that is 1!!! No array size increment!You just need to allocate one byte more
input_arrayPointer = ( char* ) realloc ( input_arrayPointer, ((filled_elements+1) * sizeof( char ) ) );
Better: always check realloc
return value. And use a temporary pointer to avoid the loss of the original pointer in case it fails.
When does realloc
fail? When it doesn't succeed in allocating the requested size. In that case, as described in man page, NULL
will be returned and assigned to input_arrayPointer
. That's not what you want.
Something like that will avoid the issue:
char *temp = realloc ( input_arrayPointer, ((filled_elements+1) * sizeof( char ) ) );
if (temp != NULL)
{
input_arrayPointer = temp;
}
Note: realloc
does not guarantee to extend the original pointer, as it has to find a contiguous memory range wide enough to contain the requested size. Instead, it finds the new memory area and copies there the original contents of the pointer (all of it, if newSize > oldSize
; newSize
bytes otherwise).