20

Why does this work :

char *fd = "myfile.txt";
struct stat buf;          

stat(fd, &buf);
int size = buf.st_size;

printf("%d",size);

But this does not work:

char *fd = "myfile.txt";
struct stat *buf;          

stat(fd, buf);
int size = buf->st_size;

printf("%d",size);
Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
necronet
  • 209
  • 1
  • 2
  • 3
  • 33
    please, don't use fd as var name for something that is not a file descriptor. – ninjalj Jun 29 '10 at 07:39
  • 3
    If you compile with `-Wall -O`, you'll get this warning from gcc: `warning: ‘buf’ is used uninitialized in this function`. – caf Jun 29 '10 at 08:43
  • Although the memory allocation issues are most critical, you should not be paying any attention to the contents of buf (or the structure pointed to by buf) until you know that 'stat()' succeeded - which you determine by checking the value it returns. If it fails, the contents of buf are meaningless. – Jonathan Leffler Jun 29 '10 at 13:58
  • This is separate from your main bug, storing buf.st_size in a variable of type int is not valid. It can overflow (which has undefined behavior), but even with the normal overflow behavior, your code will break if it encounters large files. You need to use off_t or a type you know is larger, and then cast it to a type you know how to print (for instance uintmax_t with the %ju format specifier) when you call printf. – R.. GitHub STOP HELPING ICE Jun 29 '10 at 22:56
  • do not use st_size without first checking the return value of stats functions, if it returns -1, the st_size may have invalid values.. – Ahmed Aug 12 '16 at 17:01

6 Answers6

34

The reason for it not working is that buf in the first example is allocated on the stack. In the Second example you only have a pointer to a struct stat, pointing to anywhere (probably pointing to address 0x0, i.e. a NULL pointer), you need to allocate memory for it like this:

buf = malloc(sizeof(struct stat));

Then both examples should work. When using malloc(), always remember to use free() after you are finished with using the struct stat:

free(buf);
Uli Köhler
  • 13,012
  • 16
  • 70
  • 120
Puppe
  • 4,995
  • 26
  • 27
11

It is just a simple memory allocation problem.

char *fd = "myfile.txt";
struct stat *buf;          

stat(fd, buf);
int size = buf->st_size;

printf("%d",size);

The above code only declares a pointer, but in reality, there is no memory space allocated.

you should modify the code to look like this:

char *fd = "myfile.txt";
struct stat *buf;

buf = malloc(sizeof(struct stat));

stat(fd, buf);
int size = buf->st_size;
printf("%d",size);

free(buf);

This will allocate the memory, and free after it is used.

Muhammad Anjum Kaiser
  • 3,947
  • 1
  • 18
  • 18
2

In the second, you use a pointer pointing to you-dont-know-where. stat will by chance be able to correctly fill the values in the area pointed (your program could have terminated abruptly here). Then, as you have no idea on where this data is, you use it buf->st_size but maybe someone has used this memory area that you don't own.

Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
1

It's a big difference between creating a structure or a pointer to a structure. The first code creates the structure, the second creates a pointer, to a not existing structure. Using malloc or calloc you can allocate memory and your structure will be initialized. After this you do whatever you want and at the moment when you don't need this structure anymore, you must use the free() function to free the allocated space.

Lajos Arpad
  • 361
  • 1
  • 5
  • 10
1

You haven't allocated any memory for your pointer dude.

You should allocate memory to buf.

buf = malloc(sizeof(struct stat));

now it will work.

Kumar Alok
  • 2,512
  • 8
  • 26
  • 36
0

This should fix your problem and another: file size can be either a 32 or 64-bit int. This example assumes a 64-bit machine.

#include <stat.h>
#include <errno.h>

char *file = "myfile.txt";
long long size; //st_size can be a 64-bit int.
struct stat *buf = malloc(sizeof(struct stat)); //allocates memory for stat structure.
errno = 0; //always set errno to zero first.

if(stat(file, buf) == 0)
{
    size = buf->st_size;
    printf("Size of \"%s\" is %lld bytes.\n", file, size);
}
else
{
    perror(file);    //if stat fails, print a diagnostic.
}
CyberSkull
  • 796
  • 1
  • 7
  • 16