fread: segementation fault(coredump) w/o stdlib.h

Hello All,

I tried to test a sample fread example to read a complete file
and the code is

#include <stdio.h>
#include <stdlib.h>
int main () {
  FILE * pFile;
  long lSize;
  char * buffer;
  size_t result;

  pFile = fopen ( "test.xml" , "rb" );
  if (pFile==NULL) {fputs ("File error",stderr); exit (1);}

  fseek (pFile , 0 , SEEK_END);
  lSize = ftell (pFile);
  rewind (pFile);

  buffer = (char*) malloc (sizeof(char)*lSize);
  if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

  result = fread (buffer,1,lSize,pFile);
  if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

  /* the whole file is now loaded in the memory buffer. */

  fclose (pFile);
  printf(" sizeof char :%d \n", sizeof(char));
  printf( "File: %s ", buffer);
  free (buffer);
  return 0;
}

The program worked as expected and the got the correct output.

After i removed #include <stdlib.h> from the program, it got compiled successfully but failed with the following message: Memory fault(coredump)

It failed in the fread command (checked with dbx).

Can anyone explain this behaviour?

I use AIX ver 5.

rgrds,

As the doctor would say, "don't do that". :slight_smile: Either AIX has odd integer sizes, or you're on a 64-bit system. Or perhaps both.

When you use functions that you haven't included headers for, the compiler's forced to guess what parameters the function takes and returns, and will guess they are all integers. This is often a good guess on most 32-bit systems, where int, long, and all pointers are the same size -- 32 bits. But 64-bit systems will have 64-bit pointers while still perhaps having 32-bit integers, causing pointers to get balled up and crammed through the mail slot, so to speak.

Without stdlib.h, the value malloc() gives you is corrupted, causing fread to crash when it uses it.

So, always include the headers! Just because it works 'this time' when you don't doesn't mean it will in all situations.

That's because malloc is declared in /usr/include/stdlib.h file and when you remove it from the code malloc is no longer defined and the program core dumps. Did your compiler not warn you of that.

Nope. I did not receive any warnings from the compiler. Moreover when i debug the program it did go through the malloc part without any issue but failed in the fread command.

Could you put some debug printf statements in your code so that we can see the values of lsize and buffer.
I thought malloc because if buffer is not allocated you cannot store anything there yet if (buffer == NULL) is never executed.
That is somewhat weird but I will try to reproduce it on my system running AIX ver 5.3

I'm surprised the compiler does not complain about malloc, too. Unless the OP got a symbol not resolved error, the code will run, but it may be using some library calls that are confused about sizeof(int) - as Corona says. ftell returns a long int.

A long int in 64 bit is 64 bit. a long int in 32 bit is 32 bits. That may well be the issue. I dunno. compile with symbols and then run the dbeugger on the core. That will tell you what call caused a segfault.

I have added the printf statement and yes, the program is failing because the buffer is not allocated. It fails in the strcpy function.

#include <stdio.h>
int main () {
  FILE * pFile;
  long lSize;
  char * buffer;
  size_t result;

  pFile = fopen ( "test.xml" , "rb" );
  if (pFile==NULL) {fputs ("File error",stderr); exit (1);}

  fseek (pFile , 0 , SEEK_END);
  lSize = ftell (pFile);
  rewind (pFile);

  buffer = (char*) malloc (sizeof(char)*lSize);
  if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

  printf ("\n size of buffer %ld, length of file %d\n ", sizeof(buffer), lSize);

  strcpy (buffer, "test message");
  printf( "\n Buffer Data is : %s", buffer);
  result = fread (buffer,1,lSize,pFile);
  if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

  /* the whole file is now loaded in the memory buffer. */

  fclose (pFile);
  printf(" sizeof char :%d \n", sizeof(char));
  printf( "File: %s ", buffer);
  free (buffer);
  return 0;
}

Output:

size of buffer 8, length of file 260
Memory fault(coredump)

ftell returns a long int. You've interpreted the value of the ftell return incorrectly.

Can I ask: why are you not including stdlib.h?

You gain NOTHING by not including the correct header files.

Well I guess the problem is that buffer is allocated albeit incorrectly and that explains why if (buffer == NULL) isn't executed.
Also I tried your program on my AIX system v5.3 and it runs flawlessly with or without the #include <stdlib.h> line. :confused:
This maybe because your system patch level is old specifically libc or a problem with the compiler you are using.

Hi Guys,

thanks for explaining the issue. It really helped. Of Course I am gonna use stdlib.h. I was just curious about the error and wanted to know the reason why it failed when i eliminated stdlib.

There is a mistake in my explanation...sizeof(buffer) will be 4 or 8 bytes depending on whether the system is 32/64 bits so printf output is correct...

printf ("\n size of buffer %ld, length of file %d\n ", sizeof(buffer), lSize);

Since sizeof pointer on a 64 bit system is 8 bytes. But that doesn't mean that memory is malloced for it.
What is still confusing is that control never passes to this statement below...

if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

So do as jim suggested and run it through a symbolic debugger compiled with the -g switch.

Hi,

This is the output from the debugger. I dont have GDB so used dbx

dbx a.out
Type 'help' for help.
reading symbolic information ...
(dbx) stop in main
[1] stop in main
(dbx) run
[1] stopped in main at line 8
    8     pFile = fopen ( "test.xml" , "rb" );
(dbx) n
stopped in main at line 9
    9     if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
(dbx) n
stopped in main at line 11
   11     fseek (pFile , 0 , SEEK_END);
(dbx) n
stopped in main at line 12
   12     lSize = ftell (pFile);
(dbx) n
stopped in main at line 13
   13     rewind (pFile);
(dbx) n
stopped in main at line 15
   15     buffer = (char*) malloc (sizeof(char)*lSize);
(dbx) n
stopped in main at line 16
   16     if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
(dbx) n
stopped in main at line 18
   18     printf ("\n size of buffer %ld, length of file %d\n ", sizeof(buffer), lSize);
(dbx) print buffer
(invalid char ptr (0x0000000010000ab0))
(dbx) print buffer
(invalid char ptr (0x0000000010000ab0))
(dbx) print &(*buffer)
0x0000000010000ab0
(dbx) print &buffer
0x0ffffffffffff320
(dbx) n

 size of buffer 8, length of file 216
 stopped in main at line 20
   20     strcpy (buffer, "test message");
(dbx) n

Segmentation fault in strcpy.strcpy [a.out] at 0x10000077c
0x10000077c (strcpy+0x5c) f8e50009       stdu   r7,0x8(r5)
(dbx)