runtime error with malloc - c

#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

Related

C Program does nothing if I add a function call near the end

So I am currently trying to write a fairly simple program that takes a file as input, reads it, and lexes it (lexical analysis) (I will get to parsing and interpreting later)
I have written similar programs before that worked perfectly, but surprisingly, this one hangs when I add a function at the end.
The following works perfectly:
#include <stdio.h>
#include <stdlib.h>
#include "include/slex.h"
int main(void) {
// Read the file and save it into source.
printf("start\n");
FILE* fp = fopen("test.sl", "r");
printf("fileopen\n");
fseek(fp, 0, SEEK_END);
printf("seek\n");
char* source = malloc((ftell(fp) + 1) * sizeof (char)); // +1 because of the null terminator.
printf("allocation\n");
fseek(fp, 0, SEEK_SET);
char c;
int i = 0;
while ((c = fgetc(fp)) != EOF) {
source[i++] = c;
} // Iterate through every single character in the file and store it into source.
source[i] = '\0';
fclose(fp);
// Now lex the file;
printf("Lex\n");
lexer_t lexer;
printf("lex2\n");
lexer_init(&lexer, source);
printf("lex3\n");
/*
lex(&lexer);
printf("lex4");
tl_print(&lexer.tokens);
*/
}
But when I uncomment (hope that is an actual word) lex(&lexer), it just hangs. It does not print the previous statements.
The function lex is defined in slex.c and slex.c includes slex.h.
I compiled it with gcc -Wall Wextra -o sl main.c slex.c, and it does not give me any warning, nor any error.
void lex(lexer_t* lexer):
void lex(lexer_t* lexer) {
printf("lex"); // Debugging
// Some people would call this function "make_tokens", I will call it "lex".
while (lexer->current != '\0') {
if (lexer->current == '\n') {
token_t token = {.type = NEWLINE};
tl_append(&lexer->tokens, token);
}
if (isdigit(lexer->current)) {
token_t token = {.type = INT, .int_value = lex_integer(lexer)};
tl_append(&lexer->tokens, token);
}
else if (isalpha(lexer->current)) {
token_t token = {.type = ID, .id_value = lex_identifier(lexer)};
tl_append(&lexer->tokens, token);
}
}
}
I hope someone finds a solution to my problem, because I do not understand it.
Have a nice day and thank you.
And do not hesitate to ask if you need more information, just comment it and I will edit my question.
As Bill Lynch said, Adding fflush(stdout); before lex(&lexer); solved my issue. Thanks to everyone who came by this question, really appreciate your help. I wish you all a nice day.
Credit #Bill Lynch (first comment) who noted "app will [likely] hang" with infinite loop.
It's one thing to printf() to confirm operation. It's something else to check return codes and exit with helpful message.
Below is a rewritten (untested) version of your code using short name aliases to enhance clarity of what is being performed at different locations.
#include <stdio.h>
#include <stdlib.h>
#include "include/slex.h"
void lex( lexer_t *l ) {
fprintf( stderr, "Entered lex()\n" ); // debug
char c;
while( ( c = l->current ) != '\0' ) {
token_t t = { 0 };
if( c == '\n') t.type = NEWLINE;
// still infinite loop...
// what "advances" the pointer?? Credit #Craig Estey
else if( isdigit( c ) ) t.type = INT, t.int_value = lex_integer( l );
else if( isalpha( c) ) t.type = ID, t.id_value = lex_identifier( l );
else { // equivalent to "default:" in a "switch"
fprintf( stderr, "Un-lex-able char ('%c') encountered\n", c );
exit( EXIT_FAILURE );
}
tl_append( &l->tokens, t );
}
}
int main() {
char *fname = "test.sl";
FILE* fp = fopen( fname, "r" );
if( fp == NULL ) {
fprintf( stderr, "Failed to open %s\n", fname );
exit( EXIT_FAILURE );
}
fseek( fp, 0, SEEK_END );
size_t size = ftell( fp );
fseek(fp, 0, SEEK_SET);
fprintf( stderr, "Size %zu\n", size ); // debug
char *buf = malloc( (size + 1) * sizeof *buf ); // +1 because of the null terminator.
if( buf == NULL ) {
fprintf( stderr, "Failed to alloc block %zu\n", size + 1 );
exit( EXIT_FAILURE );
}
size_t nread = fread( buf, sizeof buf[0], size, fp );
if( nread != size ) {
fprintf( stderr, "Expected %zu. Read %zu\n", size. nread );
exit( EXIT_FAILURE );
}
fclose( fp );
buf[ nread ] = '\0';
lexer_t lexer;
lexer_init( &lexer, buf );
lex( &lexer );
// free( buf ); // Unsure if you refer back to original..
tl_print( &lexer.tokens );
return 0;
}
You can add as many optimistic "making progress" printf calls as you'd like. It's the pessimistic "not working" print statements that are needed to push forward.

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

How to copy the returned token by strtok in c

When I try to copy the strtok through strcpy as suggested by the other answers on this forum. I don't get the respective number. File format is something like this 43,789,127.0.0.1 on each particular line. However I get 127 in the temp[2] location which should be 127.0.0.1 . What am I missing over here?
FILE *f = fopen("somefile", "r");
char *temp[3];
temp[0] = malloc(20);
temp[1] = malloc(20);
temp[2] = malloc(20);
const char s[1] = ",";
char *pch;
if(f != NULL)
{
char line[1024];
while(fgets(line, sizeof line, f) != NULL)
{
pch = strtok(line, s);
for(int i = 0; i<3; i++)
{
strcpy(temp[i],pch);
pch = strtok (NULL, s);
}
}
fclose(f);
} else
{
perror("somefile");
}
for(int i = 0; i<3; i++)
{
printf ("%s\n",temp[i]);
}
s is not a proper C string: const char s[1] = ","; defines it to have a size of 1, without a null terminator.
Use this instead:
const char *s = ",";
Note that a line with fewer than 2 commas will cause the program to have undefined behavior as you do not check that strtok() returns a non NULL pointer. Here is an alternative using sscanf():
#include <stdio.h>
int main(void) {
FILE *fp = fopen("somefile", "r");
char temp[3][20];
if (fp != NULL) {
char line[1024];
while (fgets(line, sizeof line, fp) != NULL) {
if (sscanf(line, "%19[^,],%19[^,],%19[^\n]", temp[0], temp[1], temp[2]) == 3) {
printf("%s\n%s\n%s\n\n", temp[0], temp[1], temp[2]);
}
}
fclose(fp);
}
return 0;
}
Note however that the above code will fail to parse lines with empty fields such as ,, because sscanf() requires a non empty string for the %[^,] conversion specifier.
Note also that strtok() would be inappropriate for such parsing too as it treats sequences of separators as a single separator, which is OK for white space but probably incorrect for ,.
the following proposed code:
cleanly compiles
is consistently indented
is appropriately horizontally and vertically spaced
corrects all the known problems in the posted code
properly checks for and handles errors
properly displays the parameters from all the lines in the file
eliminates unneeded variables
and now the code
#include <stdio.h> // fopen(), fclose(), fgets(), perror()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <string.h> // strtok(), strcpy()
#define MAX_LENGTH 20
#define MAX_PARAMETERS 3
int main( void )
{
FILE *f = fopen( "somefile", "r" );
if( !f )
{
perror( "fopen to read somefile failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
char *temp[ MAX_PARAMETERS ];
if( NULL == ( temp[0] = malloc( MAX_LENGTH ) ) )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
if( NULL == ( temp[1] = malloc( MAX_LENGTH ) ) )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
if( NULL == ( temp[2] = malloc( MAX_LENGTH ) ) )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
char line[1024];
while( fgets(line, sizeof line, f) )
{
int i;
char *pch = strtok( line, "," );
for( i = 0; i<3 && pch; i++ )
{
strcpy( temp[i], pch );
pch = strtok ( NULL, "," );
}
if( MAX_PARAMETERS != i )
{
printf( "failed to extract all parameters from line: %s\n", line );
}
else
{
for( int j = 0; j<MAX_PARAMETERS; j++ )
{
printf( "%s\n", temp[j] );
}
}
}
fclose( f );
} // end function: main

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.

Resources