0

I was wondering if someone could please clarify some questions I have concerning the read() function in Linux? Currently, I do not know how to view the buffer that is returned from the read() command. As of now, it is returning a seg fault and when I could get it to run it was returning values that were not present within the file I was trying to read. The text file: Testing a test.

So instead of getting testin (length 6) i would get testin{. I apologize if the question is confusing, if you'd like I will clarify more. Thanks for all your time and help!

        int main(int argc, char *argv[]){
            int fd = open("output_test.txt", O_RDWR | O_CREAT, 0666);
            char *buffer;
            char *copy;
            // printf("%lu\n", strlen(buffer));
            // write(fd, "testing", 7);    //this automatically writes to 
            printf("%zd\n", read(fd, &buffer, 6));
            printf("%lu\n", sizeof(buffer));
            copy = buffer;
            // printf("%lu\n", strlen(buffer));
            printf("%s\n", copy);
            }
vishal
  • 2,258
  • 1
  • 18
  • 27
chris123
  • 197
  • 3
  • 13
  • 2
    You haven't allocated any memory for `buffer` (well you have, but it's only the size of a pointer). Use `malloc` to allocate at least 6 bytes. Also turn on compiler warnings and take notice of them. And one more thing: you'll need to terminate the string with a `'\0'` before trying to print it. – Paul R Oct 23 '15 at 08:30
  • 2
    Is there such a beast as a canonical duplicate for "I'm writing stuff into an uninitialized pointer"? Such a post would be extremely valuable, as this is perhaps the most frequently asked C question of them all. – Lundin Oct 23 '15 at 08:35
  • @Lundin: I wish there were, although in this case it's subtly different as the OP is writing to the pointer itself (`&buffer`), which is something I haven't seen before - he might even have got away with it on a 64 bit system! – Paul R Oct 23 '15 at 08:37
  • 1
    @PaulR Best one I could find http://stackoverflow.com/questions/33047452/definitive-list-of-common-reasons-for-segmentation-faults. – Lundin Oct 23 '15 at 08:46
  • If `buffer` is a pointer to the actual buffer, `sizeof(buffer)` is the size of the pointer. It has nothing to do with the size of the actual buffer. – n. m. could be an AI Oct 23 '15 at 08:49
  • @Lundin: looks good, but may be "TL;DR" for some noobs - worth a try though... – Paul R Oct 23 '15 at 08:53
  • 1
    `read` does not create null-terminated strings. You need to guarantee null-termination yourself. A string of length 6 needs a buffer of length at least 7. The extra character is for null termination. You need to put the null character there yourself. – n. m. could be an AI Oct 23 '15 at 08:54
  • 1. `buffer` isn't initialized. 2. `&buffer` should be `buffer`. 3. `buffer` should be a `char[]` allocated on the stack, not a `char *` allocated dynamically: *then* `sizeof buffer` would work correctly. 4. You're ignoring the result of `read()`. It returns -1 on error, 0 at end of stream, or a positive number indicating the number of received bytes: you have to check for all three, which means you have to store it in a variable. 5. `copy = buffer;` just copies the address in `buffer`, not the contents. 6. `printf("%lu\n", sizeof(buffer));` is invalid for the reason given at (4). – user207421 Oct 23 '15 at 09:18
  • 1
    There must be a good starting point for the canonical example, both for not allocating space and reading stuff over the stack instead of into the buffer. I'm gonna star it for future dup closing. – Martin James Oct 23 '15 at 11:40

2 Answers2

4
  1. You have to allocate memory for the buffer

    char *buffer =  malloc(10);
    
  2. Please check the return of open()

  3. read() takes in void*. Change the code to

    printf("%zd\n", read(fd, buffer, 6));
    
  4. To get the length of string, use strlen() and not sizeof().

As a bonus point, your main() function has type int but you are not returning anything in the end.

user207421
  • 305,947
  • 44
  • 307
  • 483
Haris
  • 12,120
  • 6
  • 43
  • 70
1

The right way to read a buffer of known size and null-terminate it:

 #define MYSIZE 6
 char buffer[MYSIZE+1];

 size_t sz = read(fd, buffer, MYSIZE);
 if (sz < 0) 
   { .... report error }
 else 
   buffer[sz] = '\0';

If size is not known at compile time, the first two lines change to

 char* buffer = malloc(MYSIZE+1);
 if (buffer == NULL)
   { ... report an error }

The rest remains the same, and you need to free(buffer) somewhere.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Doesn't apply at all to binary data, and only applies to text data assuming the possibly partial, possibly multiple, data received is meant to be null-terminated in the first place. Hard to see the point. It is better practice just to *use* the count returned as necessary rather than adding sentinels. – user207421 Oct 25 '15 at 02:40
  • @EJP Um, it is not meant to apply to binary data, it says "null terminate" right in the first line. Binary data cannot be null-terminated. – n. m. could be an AI Oct 25 '15 at 15:55