Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

write() bad address

Tags:

c

linux

I am trying to write out the size in bytes of a string that is defined as

#define PATHA "/tmp/matrix_a"

using the code

rtn=write(data,(strlen(PATHA)*sizeof(char)),sizeof(int));
if(rtn < 0) 
    perror("Writing data_file 2 ");

I get back Writing data_file 2 : Bad address

What exactly about this is a bad address? The data file descriptor is open, and writes correctly immediately before and after the above code segment. The data to be written to the file data needs to be raw, and not ASCII.

I have also tried defining the string as a char[] with the same issue

like image 549
fotg Avatar asked Dec 05 '12 22:12

fotg


3 Answers

The second argument to write() is the address of the bytes you want to write, but you are passing the bytes you want to write themselves. In order to get an address, you must store those bytes in a variable (you can't take the address of the result of an expression). For example:

size_t patha_len = strlen(PATHA);

rtn = write(data, &patha_len, sizeof patha_len);
like image 139
caf Avatar answered Sep 28 '22 04:09

caf


The arguments to POSIX write() are:

#include <unistd.h>

ssize_t write(int fildes, const void *buf, size_t nbyte);

That's a:

  • file descriptor
  • buffer
  • size

You've passed two sizes instead of an address and a size.

Use:

rtn = write(data, PATHA, sizeof(PATHA)-1);

or:

rtn = write(data, PATHA, strlen(PATHA));

If you are seeking to write the size of the string as an int, then you need an int variable to pass to write(), like this:

int len = strlen(PATHA);

rtn = write(data, &len, sizeof(len));

Note that you can't just use a size_t variable unless you want to write a size_t; on 64-bit Unix systems, in particular, sizeof(size_t) != sizeof(int) in general, and you need to decide which size it is you want to write.

You also need to be aware that some systems are little-endian and others big-endian, and what you write using this mechanism on one type is not going to be readable on the other type (without mapping work done before or after I/O operations). You might choose to ignore this as a problem, or you might decide to use a portable format (usually, that's called 'network order', and is equivalent to big-endian), or you might decide to define that your code uses the opposite order. You can write the code so that the same logic is used on all platforms if you're careful (and all platforms get the same answers).

like image 39
Jonathan Leffler Avatar answered Sep 28 '22 03:09

Jonathan Leffler


The second argument to write() is the buffer and third argument is the size:

ssize_t write(int fd, const void *buf, size_t count);

The posted code passes the length which is interpreted as an address which is incorrect. The compiler should have emitted a warning about this (don't ignore compiler warnings and compile with the warning level at the highest level).

Change to:

rtn=write(data, PATHA, strlen(PATHA));

Note sizeof(char) is guaranteed to be 1 so it can be omitted from the size calculation.

like image 34
hmjd Avatar answered Sep 28 '22 03:09

hmjd