-1

I am trying to read a file and update a buffer with the contents. I didn't want readToBuffer return char * as I need to know the buffer size for later use. When I try to print the buffer from main It appears to be empty.

#include <stdlib.h>
#include <stdio.h>

long readToBuffer(char* path, char* buffer) {
  FILE* handle = fopen(path,"rb");
  fseek(handle,0L,SEEK_END);
  long bufferSize = ftell(handle);
  rewind(handle);
  buffer = malloc(bufferSize*sizeof(char));
  fread(buffer, sizeof(char), bufferSize, handle);
  fclose(handle);
  printf("%s",buffer);
  return bufferSize;
}

int main(int argc, char* argv[]) {
  char* path = argv[1];
  char* buffer;
  long bufferSize = readToBuffer(path, buffer);
  printf("%ld\n",bufferSize);
  printf("%s",buffer);
  return 0;
}

Given a helloWorld.txt input file why is the output as follows:

hello world
12
(null)$ 

why can I not read the buffer that was updated in the procedure readToBuffer?

beoliver
  • 5,579
  • 5
  • 36
  • 72

2 Answers2

1

When you assign to buffer in readToBuffer(), that has no effect on the variable buffer in main(). Arguments are passed by value in C, not by reference. If you want to modify the caller's variable, you need to pass a pointer to the variable.

Note also that fread() doesn't add a null terminator to the input, so printing the buffer with %s format is not valid. You need to allocate an extra byte in the buffer and put 0 there.

#include <stdlib.h>
#include <stdio.h>

long readToBuffer(char* path, char** buffer) {
  FILE* handle = fopen(path,"rb");
  fseek(handle,0L,SEEK_END);
  long bufferSize = ftell(handle)+1;
  rewind(handle);
  *buffer = malloc(bufferSize*sizeof(char));
  fread(*buffer, sizeof(char), bufferSize-1, handle);
  buffer[buffersize-1] = 0;
  fclose(handle);
  printf("%s", *buffer);
  return bufferSize;
}

int main(int argc, char* argv[]) {
  char* path = argv[1];
  char* buffer;
  long bufferSize = readToBuffer(path, &buffer);
  printf("%ld\n",bufferSize);
  printf("%s",buffer);
  return 0;
}

For more information about pointers, see What are the barriers to understanding pointers and what can be done to overcome them?

Community
  • 1
  • 1
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • what I don't understand then is why the signature for `fread()` is `fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);` i.e **no** pointers to pointers – beoliver Sep 18 '15 at 22:02
  • `fread` doesn't need to modify the pointer argument, it's just writing into the buffer that the pointer points to. – Barmar Sep 18 '15 at 22:06
  • 1
    Your function is different because it allocates the buffer and needs to change the caller's `buffer` variable to point to that new buffer. – Barmar Sep 18 '15 at 22:06
  • I can't edit at it is only one character, but `printf("%s",buffer);` in the `readToBuffer` procedure is missing a `*` – beoliver Sep 18 '15 at 22:22
0

Because you are not changing the data the buffer points to, you are trying to edit what pointer points to. When your function exits the address of buffer is unchanged, and that memory is currently leaked.

To do this properly you need to pass a pointer to a pointer and change your function signature.

in this case pass in &buffer alter the signature to use a **char buffer and the assignment to buffer[0] or *buffer as in *buffer = malloc ....

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46