Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to use cerr when handling bad_alloc?

Is it safe to use std::cerr like this?

try 
{
      Something();
} 
catch(std::bad_alloc) 
{
    cerr << "Out of memory!";
}

Does it use dynamic memory? If it fails, will it throw an exception or just not output anything?

like image 584
gist Avatar asked Oct 31 '22 18:10

gist


2 Answers

Simple case

There is one failing big allocation -possibly due to programmer's mistake-

int main() 
{

    try {
        std::size_t bytesToAllocate;
        std::cin >> bytesToAllocate;

        std::unique_ptr<char> ptr { new char[bytesToAllocate - 1] };
        // ops, if user enters 0 or extraction fails we get 
        // std::numeric_limits<std::size_t>::max() -1 bytes to allocate

    } catch (const std::bad_alloc& e) {
            std::cerr << "Failed to allocate memory.\n";
    }
}

Here, even if new fails, we definitely have more memory because there was none used before.

Realistic case

If, for some unspecified reason, a character insertion fails, the internal failbit is enabled i.e setstate(std::ios_base::failbit) and, if exception is set for failbit, an exception is thrown. Moreover, if an exception is thrown during an insertion, badbit is set and, if exception is set on badbit, the exception is rethrown.

However, AFAIK, it is left uncovered and therefore unspecified whether such operation allocates memory or not and how it's done. Your program could be killed because of out-of-memory protections and so without having chance to catch the exception, if the whole process of exception propagating is possible at all in that condition.

like image 149
edmz Avatar answered Nov 15 '22 04:11

edmz


The standard(27.7.3.6, page 1057) defines some requirements for formatted output functions in ostreams:

Each formatted output function begins execution by constructing an object of class sentry . If this object returns true when converted to a value of type bool , the function endeavors to generate the requested output. If the generation fails, then the formatted output function does setstate(ios_base::failbit) , which might throw an exception. If an exception is thrown during output, then ios::badbit is turned on 328 in *this ’s error state. If (exceptions()&badbit) != 0 then the exception is rethrown. Whether or not an exception is thrown, the sentry object is destroyed before leaving the formatted output function. If no exception is thrown, the result of the formatted output function is *this .

(Emphasis mine)

For the construction of the sentry object (as with the construction of any object), the program will require more memory. Whether it is static or dynamic memory is left unspecified. Also, as blacks' answer sums up nicely, the standard defines that an exception may be thrown when failbit is enabled.

like image 42
Cássio Renan Avatar answered Nov 15 '22 04:11

Cássio Renan