cmemory-managementout-of-memory

Output to stdout or stderr when out of memory


How can I output something when out of memory?

I have a custom set of malloc[, realloc and calloc] and free functions. For now the project just uses them as a wrapper for the normal versions of the functions. These wrapper functions terminate the program and should give an output to indicate the error.

At the moment the function to output the error message looks like this:

#ifdef __linux__
void memory_error() {
    if (errno == ENOMEM)
        printf("%s\n", "Out of memory or memory is limited. Fatal error. The program needs to terminate.");
    else
        printf("%s\n", "Memory allocation failed. Fatal error. The program needs to terminate.");
}
#else
void memory_error() {
    printf("%s\n", "Memory allocation failed, likely due to being out of "
                   "memory or memory being limited for this program. "
                   "Fatal error. The program needs to terminate.");
}
#endif

The problem is that printf() sometimes allocates memory and if I am out of memory, that will fail. Does fwrite() allocate memory? And if so, is there a portable (so no write system call) option to output something without having to allocate more memory?

So far as a working solution for unix systems I could do this:

#ifdef __unix__
#define write_str_no_alloc(str) write(STDERR_FILENO, str, sizeof(str))
#else
#define write_str_no_alloc(str) ???
#endif

I am missing a solution for windows. I would prefer a general solution for both, but this would work for me.


Solution

  • On POSIX systems the write function directly invokes the write system call, so no memory allocation happens there.

    Windows has a _write function which is part of its POSIX compatibility layer, and is also documented to invoke the OS directly without buffering:

    These functions invoke the operating system directly for lower-level operation than that provided by stream I/O. Low-level input and output calls don't buffer or format data.

    So you can do this:

    #ifdef _MSC_VER
    #include <io.h>
    #define write_str_no_alloc(str) _write(2, str, sizeof(str))
    #else
    #define write_str_no_alloc(str) write(STDERR_FILENO, str, sizeof(str))
    #endif
    

    Note that this requires the argument to be a string literal or an array, otherwise sizeof won't give the desired result.