2

I want to build an unique error number, which consists of a random number and the errno of a system call. Example:

#define ERRID(ERRNO) ((uint32_t)rand() << 16 | (uint32_t)(ERRNO) & 0xFFFF)

I need to know how many bits are required to store an errno value.

I know it is defined as int. But the total number of errors is much lower than 9,223,372,036,854,775,807 on a 64 bit system. On my Debian the maximum number seems to be 529.

dpkg -L linux-headers-3.16.0-4-common|
grep errno.h|
xargs cat|
awk '/^#define/{print $3}'|
sort -rn|
head -1
529

So uint16_t seems to be enough to store the errno.

But how to be sure? How can I find out how many errnos the operating system actually uses? Is it documented anywhere?

ceving
  • 21,900
  • 13
  • 104
  • 178
  • 4
    **Why** you have to use `int16_t` if it's defined as `int`?! OS is free to add any error number wherever it wants in the next patch, two days after you released your application assuming it'll fit a 16 bit signed integer. – Adriano Repetti Sep 18 '15 at 08:19
  • 1
    Can you use a structure, like `struct UniqueError { int randNumber, int errnoNumber };`? That is what I would consider, in terms of portability, instead of relying on the "maximum" value of errno (which might change over time and from system to system) – Andreas Fester Sep 18 '15 at 08:19
  • 2
    `int` is only 32 bits on 64-bit Linux. – Paul R Sep 18 '15 at 08:21
  • 1
    @AdrianoRepetti Please read the first sentence of my question. – ceving Sep 18 '15 at 08:35
  • @Andreas That is the reason why I ask, if it is specified in a standard. – ceving Sep 18 '15 at 08:36
  • Unfortunately you can't make a good assumption about that. Yes you may set lower 16 bit to 0 and use higher 16 bit...or to use an hash code for your error name... – Adriano Repetti Sep 18 '15 at 08:40
  • Although all the system I've seen started at 1 and incremented their errno values from there, and I havn't seen any system with an errno value > 1000 yet, there are no guarantees in any standard. That said, on linux there's an unwritten rule that errno can only go up to 4095 – nos Sep 18 '15 at 09:16

2 Answers2

4

There is no portable way to do this. POSIX (and C) allows the implementation to use all positive int values as error numbers, there is no constant for the maximum number used, and there may not be an integer type larger than int.

dpi
  • 1,919
  • 17
  • 17
2

You can just pass around a handle instead which contains both the errno error code and the random identifier (I assume you want this to be a unique ID in order to be able to identify specific instances of errors later…?)

struct ErrorID {
    int errno_error;
    int rand_id;
}

ErrorID this_func_can_fail()
{
    return (ErrorID){ .errno_error = errno, .rand_id = rand() };
}

This compiles:

#include <errno.h>
#include <stdlib.h>

struct ErrorID {
    int errno_error;
    int rand_id;
};

struct ErrorID this_func_can_fail()
{
    return (struct ErrorID){ .errno_error = errno, .rand_id = rand() };
}

int main (int argc, char *argv[])
{
  this_func_can_fail();
  return 0;
}
ceving
  • 21,900
  • 13
  • 104
  • 178