Skip to main content
Tweeted twitter.com/StackCodeReview/status/1394261437464317959
added 2 characters in body
Source Link
Linny
  • 10.4k
  • 5
  • 37
  • 99
#pragma once
#include <iostream>
#include <windows.h>
#include <sstream>
#include <Psapi.h>

// Author: https://github.com/TheRacc2
// Other Help: https://github.com/dgoguerra/, for the bytes_to_size function (modified from the "humanSize" function found in https://gist.github.com/dgoguerra/7194777)
// Repository: https://github.com/TheRacc2/error_handler/
// Report issues here: https://github.com/TheRacc2/error_handler/issues

constexpr const char* name = "Error Handler";

namespace helpers {
    // Convert bytes into readable sizes, E.G: 1024B -> 1KB, 1024000B -> 1MB
    //
    // call as such:
    // const char* sign = bytes_to_size(1024);
    const char* bytes_to_size(int bytes) {
        const char* units[] = { "B", "KB", "MB", "GB", "TB" };
        const int size = sizeof(units) / sizeof(units[0]) - 1;

        int i = 0;
        double outside_bytes = bytes;

        if (bytes > 1024)
            for (; (bytes / 1024) > 0 && i < size; i++, bytes /= 1024)
                outside_bytes = bytes / 1024;

        static char final[12];
        snprintf(final, 12, "%.01f %s", outside_bytes, units[i]);
        return final;
    }
}

namespace error_handler {
    // Use this in a "try, catch" situation, the send to developers function doesn't need to be provided.
    // 
    // call as such:
    // try {
    //     your_function_or_code();
    // } CATCH(send_log_to_developer(ex))
    #define CATCH(send_to_developers_function) \
    catch (const std::exception& ex) { \
        std::stringstream error; \
        error << ex.what(); \
        error << "\n\n"; \
        error << "Would you like to report this to the developers? Should your request be seen, this crash may be prevented."; \
        \
        if (MessageBoxA(nullptr, error.str().c_str(), name, MB_YESNO) == IDYES) { \
            send_to_developers_function; \
            MessageBoxA(nullptr, "Thank you for reporting this!", name, MB_OK); \
        } \
    }

    // Call this when something needs to go wrong, formatted like "printf". The second argument doesn't need to be provided.
    // 
    // call as such:
    // THROW("You didn't use this right! You used this like: %s", "throw()")
    // 
    // output:
    // "You didnt use this right! You used this like: throw()"
    #define THROW(text, ...) \
    error_handler::throw_ex(text, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__);

    // You shouldn't manually call this function, as you have to provide the file, function and line.
    // Use the "THROW" macro instead.
    template <typename... Args>
    void throw_ex(const char* text, const char* file, const char* function, const int& line, Args... args) {
        char message[128];
        snprintf(message, 128, text, args...);

        std::stringstream stream;
        stream << message << "\n\n";

        PROCESS_MEMORY_COUNTERS_EX pmc;
        K32GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc), sizeof(pmc));

        stream <<
            "{\n" <<
            "    File: \"" << file << "\",\n"
            "    Function: \"" << function << "\",\n"
            "    Line: " << line << ",\n"
            "    Memory: \"" << helpers::bytes_to_size(pmc.PrivateUsage) << "\"\n"
            "}"
        ;

        throw std::exception(stream.str().c_str());
    }
}
```
#pragma once
#include <iostream>
#include <windows.h>
#include <sstream>
#include <Psapi.h>

// Author: https://github.com/TheRacc2
// Other Help: https://github.com/dgoguerra/, for the bytes_to_size function (modified from the "humanSize" function found in https://gist.github.com/dgoguerra/7194777)
// Repository: https://github.com/TheRacc2/error_handler/
// Report issues here: https://github.com/TheRacc2/error_handler/issues

constexpr const char* name = "Error Handler";

namespace helpers {
    // Convert bytes into readable sizes, E.G: 1024B -> 1KB, 1024000B -> 1MB
    //
    // call as such:
    // const char* sign = bytes_to_size(1024);
    const char* bytes_to_size(int bytes) {
        const char* units[] = { "B", "KB", "MB", "GB", "TB" };
        const int size = sizeof(units) / sizeof(units[0]) - 1;

        int i = 0;
        double outside_bytes = bytes;

        if (bytes > 1024)
            for (; (bytes / 1024) > 0 && i < size; i++, bytes /= 1024)
                outside_bytes = bytes / 1024;

        static char final[12];
        snprintf(final, 12, "%.01f %s", outside_bytes, units[i]);
        return final;
    }
}

namespace error_handler {
    // Use this in a "try, catch" situation, the send to developers function doesn't need to be provided.
    // 
    // call as such:
    // try {
    //     your_function_or_code();
    // } CATCH(send_log_to_developer(ex))
    #define CATCH(send_to_developers_function) \
    catch (const std::exception& ex) { \
        std::stringstream error; \
        error << ex.what(); \
        error << "\n\n"; \
        error << "Would you like to report this to the developers? Should your request be seen, this crash may be prevented."; \
        \
        if (MessageBoxA(nullptr, error.str().c_str(), name, MB_YESNO) == IDYES) { \
            send_to_developers_function; \
            MessageBoxA(nullptr, "Thank you for reporting this!", name, MB_OK); \
        } \
    }

    // Call this when something needs to go wrong, formatted like "printf". The second argument doesn't need to be provided.
    // 
    // call as such:
    // THROW("You didn't use this right! You used this like: %s", "throw()")
    // 
    // output:
    // "You didnt use this right! You used this like: throw()"
    #define THROW(text, ...) \
    error_handler::throw_ex(text, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__);

    // You shouldn't manually call this function, as you have to provide the file, function and line.
    // Use the "THROW" macro instead.
    template <typename... Args>
    void throw_ex(const char* text, const char* file, const char* function, const int& line, Args... args) {
        char message[128];
        snprintf(message, 128, text, args...);

        std::stringstream stream;
        stream << message << "\n\n";

        PROCESS_MEMORY_COUNTERS_EX pmc;
        K32GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc), sizeof(pmc));

        stream <<
            "{\n" <<
            "    File: \"" << file << "\",\n"
            "    Function: \"" << function << "\",\n"
            "    Line: " << line << ",\n"
            "    Memory: \"" << helpers::bytes_to_size(pmc.PrivateUsage) << "\"\n"
            "}"
        ;

        throw std::exception(stream.str().c_str());
    }
}
```
#pragma once
#include <iostream>
#include <windows.h>
#include <sstream>
#include <Psapi.h>

// Author: https://github.com/TheRacc2
// Other Help: https://github.com/dgoguerra/, for the bytes_to_size function (modified from the "humanSize" function found in https://gist.github.com/dgoguerra/7194777)
// Repository: https://github.com/TheRacc2/error_handler/
// Report issues here: https://github.com/TheRacc2/error_handler/issues

constexpr const char* name = "Error Handler";

namespace helpers {
    // Convert bytes into readable sizes, E.G: 1024B -> 1KB, 1024000B -> 1MB
    //
    // call as such:
    // const char* sign = bytes_to_size(1024);
    const char* bytes_to_size(int bytes) {
        const char* units[] = { "B", "KB", "MB", "GB", "TB" };
        const int size = sizeof(units) / sizeof(units[0]) - 1;

        int i = 0;
        double outside_bytes = bytes;

        if (bytes > 1024)
            for (; (bytes / 1024) > 0 && i < size; i++, bytes /= 1024)
                outside_bytes = bytes / 1024;

        static char final[12];
        snprintf(final, 12, "%.01f %s", outside_bytes, units[i]);
        return final;
    }
}

namespace error_handler {
    // Use this in a "try, catch" situation, the send to developers function doesn't need to be provided.
    // 
    // call as such:
    // try {
    //     your_function_or_code();
    // } CATCH(send_log_to_developer(ex))
    #define CATCH(send_to_developers_function) \
    catch (const std::exception& ex) { \
        std::stringstream error; \
        error << ex.what(); \
        error << "\n\n"; \
        error << "Would you like to report this to the developers? Should your request be seen, this crash may be prevented."; \
        \
        if (MessageBoxA(nullptr, error.str().c_str(), name, MB_YESNO) == IDYES) { \
            send_to_developers_function; \
            MessageBoxA(nullptr, "Thank you for reporting this!", name, MB_OK); \
        } \
    }

    // Call this when something needs to go wrong, formatted like "printf". The second argument doesn't need to be provided.
    // 
    // call as such:
    // THROW("You didn't use this right! You used this like: %s", "throw()")
    // 
    // output:
    // "You didnt use this right! You used this like: throw()"
    #define THROW(text, ...) \
    error_handler::throw_ex(text, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__);

    // You shouldn't manually call this function, as you have to provide the file, function and line.
    // Use the "THROW" macro instead.
    template <typename... Args>
    void throw_ex(const char* text, const char* file, const char* function, const int& line, Args... args) {
        char message[128];
        snprintf(message, 128, text, args...);

        std::stringstream stream;
        stream << message << "\n\n";

        PROCESS_MEMORY_COUNTERS_EX pmc;
        K32GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc), sizeof(pmc));

        stream <<
            "{\n" <<
            "    File: \"" << file << "\",\n"
            "    Function: \"" << function << "\",\n"
            "    Line: " << line << ",\n"
            "    Memory: \"" << helpers::bytes_to_size(pmc.PrivateUsage) << "\"\n"
            "}"
        ;

        throw std::exception(stream.str().c_str());
    }
}
edited tags
Link
Toby Speight
  • 81.8k
  • 14
  • 101
  • 309
Source Link

Custom Error Handler Library in C++

Is this code clean and optimized? When taking memory snapshots, it seems a bit high. Anything I have done wrong or can do to optimize it?

#pragma once
#include <iostream>
#include <windows.h>
#include <sstream>
#include <Psapi.h>

// Author: https://github.com/TheRacc2
// Other Help: https://github.com/dgoguerra/, for the bytes_to_size function (modified from the "humanSize" function found in https://gist.github.com/dgoguerra/7194777)
// Repository: https://github.com/TheRacc2/error_handler/
// Report issues here: https://github.com/TheRacc2/error_handler/issues

constexpr const char* name = "Error Handler";

namespace helpers {
    // Convert bytes into readable sizes, E.G: 1024B -> 1KB, 1024000B -> 1MB
    //
    // call as such:
    // const char* sign = bytes_to_size(1024);
    const char* bytes_to_size(int bytes) {
        const char* units[] = { "B", "KB", "MB", "GB", "TB" };
        const int size = sizeof(units) / sizeof(units[0]) - 1;

        int i = 0;
        double outside_bytes = bytes;

        if (bytes > 1024)
            for (; (bytes / 1024) > 0 && i < size; i++, bytes /= 1024)
                outside_bytes = bytes / 1024;

        static char final[12];
        snprintf(final, 12, "%.01f %s", outside_bytes, units[i]);
        return final;
    }
}

namespace error_handler {
    // Use this in a "try, catch" situation, the send to developers function doesn't need to be provided.
    // 
    // call as such:
    // try {
    //     your_function_or_code();
    // } CATCH(send_log_to_developer(ex))
    #define CATCH(send_to_developers_function) \
    catch (const std::exception& ex) { \
        std::stringstream error; \
        error << ex.what(); \
        error << "\n\n"; \
        error << "Would you like to report this to the developers? Should your request be seen, this crash may be prevented."; \
        \
        if (MessageBoxA(nullptr, error.str().c_str(), name, MB_YESNO) == IDYES) { \
            send_to_developers_function; \
            MessageBoxA(nullptr, "Thank you for reporting this!", name, MB_OK); \
        } \
    }

    // Call this when something needs to go wrong, formatted like "printf". The second argument doesn't need to be provided.
    // 
    // call as such:
    // THROW("You didn't use this right! You used this like: %s", "throw()")
    // 
    // output:
    // "You didnt use this right! You used this like: throw()"
    #define THROW(text, ...) \
    error_handler::throw_ex(text, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__);

    // You shouldn't manually call this function, as you have to provide the file, function and line.
    // Use the "THROW" macro instead.
    template <typename... Args>
    void throw_ex(const char* text, const char* file, const char* function, const int& line, Args... args) {
        char message[128];
        snprintf(message, 128, text, args...);

        std::stringstream stream;
        stream << message << "\n\n";

        PROCESS_MEMORY_COUNTERS_EX pmc;
        K32GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc), sizeof(pmc));

        stream <<
            "{\n" <<
            "    File: \"" << file << "\",\n"
            "    Function: \"" << function << "\",\n"
            "    Line: " << line << ",\n"
            "    Memory: \"" << helpers::bytes_to_size(pmc.PrivateUsage) << "\"\n"
            "}"
        ;

        throw std::exception(stream.str().c_str());
    }
}
```