6
votes

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

5

5 Answers

4
votes

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);
4
votes

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).

3
votes

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.

2
votes

The Bad address error has already been answered. If you want to write the size of a string just use printf.

printf("Length: %d\n", strlen(data));

Either that, or you can write a function that will convert an integer to a string and print that out... I prefer printf :)

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

is what you want I think. Arguments are supposed to be

  1. file descriptor (data)
  2. the source buffer (your string constant PATHA)
  3. The number of bytes to pull from that buffer (measured using strlen() on the same PATHA constant)

Also, to be complete, you should always check rtn for how many characters you've written. You're not guaranteed that you write() all the bytes requested on all descriptor types. So sometimes you end up writing it in chunks, determined by the amount it answers that it wrote, vs how many you know you have yet to write still then.