diff --git a/src/conn.cpp b/src/conn.cpp index a5479e3..1767b25 100644 --- a/src/conn.cpp +++ b/src/conn.cpp @@ -52,7 +52,7 @@ const char* ConnBase::peerLabel() const void ConnBase::connect(bufferevent* bev) { if(!bev) - throw std::bad_alloc(); + throw BAD_ALLOC(); assert(!this->bev && state==Holdoff); this->bev.reset(bev); diff --git a/src/evhelper.cpp b/src/evhelper.cpp index 103f0a0..e88d613 100644 --- a/src/evhelper.cpp +++ b/src/evhelper.cpp @@ -951,7 +951,7 @@ bool EvOutBuf::refill(size_t more) vec.iov_len = base ? pos - base : 0u; if(base && evbuffer_commit_space(backing, &vec, 1)) - throw std::bad_alloc(); // leak? + throw BAD_ALLOC(); // leak? limit = base = pos = nullptr; @@ -975,7 +975,7 @@ bool EvInBuf::refill(size_t needed) // drain consumed if(base && evbuffer_drain(backing, pos-base)) - throw std::bad_alloc(); + throw BAD_ALLOC(); limit = base = pos = nullptr; @@ -1016,7 +1016,7 @@ void to_evbuf(evbuffer *buf, const Header& H, bool be) EvOutBuf M(be, buf, 8); to_wire(M, H); if(!M.good()) - throw std::bad_alloc(); + throw BAD_ALLOC(); } } // namespace impl diff --git a/src/evhelper.h b/src/evhelper.h index 1ef7dc2..658a6f7 100644 --- a/src/evhelper.h +++ b/src/evhelper.h @@ -63,7 +63,7 @@ struct owned_ptr : public std::unique_ptr constexpr owned_ptr() {} explicit owned_ptr(T* ptr) : std::unique_ptr(ptr) { if(!*this) - throw std::bad_alloc(); + throw BAD_ALLOC(); } }; diff --git a/src/serverconn.cpp b/src/serverconn.cpp index 8a1bf4d..fb981bb 100644 --- a/src/serverconn.cpp +++ b/src/serverconn.cpp @@ -101,7 +101,7 @@ ServerConn::ServerConn(ServIface* iface, evutil_socket_t sock, struct sockaddr * assert(M.good() && H.good()); if(evbuffer_add(tx, buf.data(), M.save()-buf.data())) - throw std::bad_alloc(); + throw BAD_ALLOC(); statTx += M.save()-buf.data(); } diff --git a/src/unittest.cpp b/src/unittest.cpp index 1be9da8..52a153d 100644 --- a/src/unittest.cpp +++ b/src/unittest.cpp @@ -1,4 +1,4 @@ -/** +/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvxs is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. @@ -18,6 +18,10 @@ #endif #include +#include +#define epicsStdioStdStreams +#define epicsStdioStdPrintfEtc +#include #include "pvxs/unittest.h" #include "utilpvt.h" @@ -37,6 +41,29 @@ void testSetup() #endif } +namespace impl { +loc_bad_alloc::loc_bad_alloc(const char *file, int line) +{ + if(auto sep = strrchr(file, '/')) { + file = sep+1; + } +#ifdef _WIN32 + if(auto sep = strrchr(file, '\\')) { + file = sep+1; + } +#endif + epicsSnprintf(msg, sizeof(msg)-1u, "bad_alloc %s:%d", file, line); +} + +loc_bad_alloc::~loc_bad_alloc() {} + +const char* loc_bad_alloc::what() const noexcept +{ + return msg; +} + +} // namespace impl + void cleanup_for_valgrind() { for(auto& pair : instanceSnapshot()) { diff --git a/src/util.cpp b/src/util.cpp index 9c6ce84..ebb915f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -236,7 +236,7 @@ struct SocketPair { auto err = evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, s); #endif if(err) - throw std::bad_alloc(); + throw BAD_ALLOC(); } ~SocketPair() { epicsSocketDestroy(s[0]); diff --git a/src/utilpvt.h b/src/utilpvt.h index 38c49f6..b17fd50 100644 --- a/src/utilpvt.h +++ b/src/utilpvt.h @@ -56,6 +56,21 @@ struct promote_print { static int op(const char& v) { return v; }}; template<> struct promote_print { static unsigned op(const char& v) { return v; }}; +/* specialization of bad_alloc which notes the location from which + * the exception originates. + */ +struct PVXS_API loc_bad_alloc final : public std::bad_alloc +{ + loc_bad_alloc(const char *file, int line); + virtual ~loc_bad_alloc(); + + virtual const char* what() const noexcept override final; + +private: + char msg[64]; +}; +#define BAD_ALLOC() ::pvxs::impl::loc_bad_alloc(__FILE__, __LINE__) + //! in-line string builder (eg. for exception messages) //! eg. @code throw std::runtime_error(SB()<<"Some message"<<42); @endcode struct SB {