after some struggles I just finished pset6.

In particular my load function caused quite some pain. I thought I'd be spart and instead of reading the file in chunks of 512 bytes and doing a lot of reallocation, I tried to find out the size of the file, malloc enough memory to put it in and copy the whole thing.

After some google searching I found this trick to get the size of the file:

fseek(file, 0, SEEK_END);
size = ftell(file);
fseek(file, 0, SEEK_SET);

It didn't work and I kept getting segmentation faults. So I tried it "classic" way with reading 512 bytes at a time into buffer and reallocating memory until the end of the file. This worked fine, but I am still wondering, why the other way didn't.

Did I do it wrong? Or is there some other explanation why it didn't work in this case?

Thanks in advance for any insights.



I'll quote some useful answers, because this question has been asked before:

First Kareem Zidade on a post on facebook:

You'll learn more about that in the following few weeks of the course, but PHP is an "interpreted" language, meaning PHP code goes through a program called an "interpreter", that interprets it, and produces output (e.g., the final HTML, JavaScript, etc).

So what a web server, like ours, typically does upon receiving a request for a PHP file is invoking a PHP interpreter, passing it the file (or a path thereto) and possibly parameters, and maybe responding with its output (if any).

If you look at the code for the interpret function, you'll find it uses popen to start a PHP interpreter process and create a "pipe" (https://linux.die.net/man/7/pipe) to communicate with that process, specifically expecting output from it, as denoted by the "r" passed as a second arg to popen.

For that reason, we cannot fseek through the data before reading it in advance, and buffering it.

and then this stackoverflow answer:

The FILE returned by popen is not a regular file, but a thing called a pipe. (That's what the p stands for.) Data flows through the pipe from the stdout of the command you invoked to your program. Because it's a communications channel and not a file on disk, a pipe does not have a definite size, and you cannot seek to different locations in the data stream. Therefore, fseek and ftell will both fail when applied to this FILE, and that's what a -1 return value means. If you inspect errno immediately after the call to ftell you will discover that it has the value ESPIPE, which means "You can't do that to a pipe."

If you're trying to read all of the output from the command into a single char* buffer, the only way to do it is to repeatedly call one of the read functions until it indicates end-of-file, and enlarge the buffer as necessary using realloc. If the output is potentially large, it would be better to change your program to process the data in chunks, if there's any way to do that.


If this is enough to clarify things, please click the check mark on the left to accept the answer.

  • Thank you! This explains it very well. – kafe Dec 12 '16 at 7:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .