namespace CVC4 {
#ifdef CVC4_DEBUG
-CVC4_THREADLOCAL(const char*) s_debugLastException = NULL;
+//CVC4_THREADLOCAL(const char*) s_debugLastException = NULL;
#endif /* CVC4_DEBUG */
+
void AssertionException::construct(const char* header, const char* extra,
const char* function, const char* file,
unsigned line, const char* fmt,
setMessage(string(buf));
#ifdef CVC4_DEBUG
- if(s_debugLastException == NULL) {
- // we leak buf[] but only in debug mode with assertions failing
- s_debugLastException = buf;
+ LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
+ if(buffer != NULL){
+ if(buffer->getContents() == NULL) {
+ buffer->setContents(buf);
+ }
}
-#else /* CVC4_DEBUG */
- delete [] buf;
#endif /* CVC4_DEBUG */
+ delete [] buf;
}
void AssertionException::construct(const char* header, const char* extra,
setMessage(string(buf));
+
#ifdef CVC4_DEBUG
- // we leak buf[] but only in debug mode with assertions failing
- if(s_debugLastException == NULL) {
- s_debugLastException = buf;
+ LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
+ if(buffer != NULL){
+ if(buffer->getContents() == NULL) {
+ buffer->setContents(buf);
+ }
}
-#else /* CVC4_DEBUG */
- delete [] buf;
#endif /* CVC4_DEBUG */
+ delete [] buf;
}
#ifdef CVC4_DEBUG
#ifdef CVC4_DEBUG
-extern CVC4_THREADLOCAL(const char*) s_debugLastException;
-
/**
* Special assertion failure handling in debug mode; in non-debug
* builds, the exception is thrown from the macro. We factor out this
// details of the exception
# define AlwaysAssert(cond, msg...) \
do { \
- if(__builtin_expect( ( ! (cond) ), false )) { \
+ if(__builtin_expect( ( ! (cond) ), false )) { \
/* save the last assertion failure */ \
- const char* lastException = ::CVC4::s_debugLastException; \
+ ::CVC4::LastExceptionBuffer* buffer = \
+ ::CVC4::LastExceptionBuffer::getCurrent(); \
+ const char* lastException = (buffer == NULL) ? \
+ NULL : buffer->getContents(); \
::CVC4::AssertionException exception(#cond, __PRETTY_FUNCTION__, __FILE__, __LINE__, ## msg); \
::CVC4::debugAssertionFailed(exception, lastException); \
} \
#include "base/exception.h"
-#include <string>
+#include <cstdarg>
#include <cstdio>
#include <cstdlib>
-#include <cstdarg>
+#include <cstring>
+#include <string>
#include "base/cvc4_assert.h"
namespace CVC4 {
+CVC4_THREADLOCAL(LastExceptionBuffer*) LastExceptionBuffer::s_currentBuffer = NULL;
+
+LastExceptionBuffer::LastExceptionBuffer() : d_contents(NULL) {}
+
+LastExceptionBuffer::~LastExceptionBuffer() {
+ if(d_contents != NULL){
+ free(d_contents);
+ d_contents = NULL;
+ }
+}
+
+void LastExceptionBuffer::setContents(const char* string) {
+ if(d_contents != NULL){
+ free(d_contents);
+ d_contents = NULL;
+ }
+
+ if(string != NULL){
+ d_contents = strdup(string);
+ }
+}
+
char* IllegalArgumentException::s_header = "Illegal argument detected";
std::string IllegalArgumentException::formatVariadic() {
setMessage(string(buf));
#ifdef CVC4_DEBUG
- if(s_debugLastException == NULL) {
- // we leak buf[] but only in debug mode with assertions failing
- s_debugLastException = buf;
+ LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
+ if(buffer != NULL){
+ if(buffer->getContents() == NULL) {
+ buffer->setContents(buf);
+ }
}
-#else /* CVC4_DEBUG */
- delete [] buf;
#endif /* CVC4_DEBUG */
+ delete [] buf;
}
void IllegalArgumentException::construct(const char* header, const char* extra,
setMessage(string(buf));
#ifdef CVC4_DEBUG
- if(s_debugLastException == NULL) {
- // we leak buf[] but only in debug mode with assertions failing
- s_debugLastException = buf;
+ LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
+ if(buffer != NULL){
+ if(buffer->getContents() == NULL) {
+ buffer->setContents(buf);
+ }
}
-#else /* CVC4_DEBUG */
- delete [] buf;
#endif /* CVC4_DEBUG */
+ delete [] buf;
}
} /* namespace CVC4 */
#include <stdexcept>
#include <string>
+#include "base/tls.h"
+
namespace CVC4 {
class CVC4_PUBLIC Exception : public std::exception {
} \
}
+class CVC4_PUBLIC LastExceptionBuffer {
+public:
+ LastExceptionBuffer();
+ ~LastExceptionBuffer();
+
+ void setContents(const char* string);
+ const char* getContents() const { return d_contents; }
+
+ static LastExceptionBuffer* getCurrent() { return s_currentBuffer; }
+ static void setCurrent(LastExceptionBuffer* buffer) { s_currentBuffer = buffer; }
+
+ static const char* currentContents() {
+ return (getCurrent() == NULL) ? NULL : getCurrent()->getContents();
+ }
+
+private:
+ /* Disallow copies */
+ LastExceptionBuffer(const LastExceptionBuffer&) CVC4_UNUSED;
+ LastExceptionBuffer& operator=(const LastExceptionBuffer&) CVC4_UNUSED;
+
+ char* d_contents;
+
+ static CVC4_THREADLOCAL(LastExceptionBuffer*) s_currentBuffer;
+}; /* class LastExceptionBuffer */
}/* CVC4 namespace */
#include <iostream>
#include <cstring>
+#include "base/exception.h"
#include "base/output.h"
#include "expr/attribute.h"
Exception(message),
d_node(new Node(node)) {
#ifdef CVC4_DEBUG
- // yes, this leaks memory, but only in debug modes with exceptions occurring
- s_debugLastException = strdup(toString().c_str());
+ LastExceptionBuffer* current = LastExceptionBuffer::getCurrent();
+ if(current != NULL){
+ current->setContents(toString().c_str());
+ }
#endif /* CVC4_DEBUG */
}
namespace CVC4 {
#ifdef CVC4_DEBUG
- extern CVC4_THREADLOCAL(const char*) s_debugLastException;
+//extern CVC4_THREADLOCAL(const char*) s_debugLastException;
#endif /* CVC4_DEBUG */
namespace main {
"CVC4 threw an \"unexpected\" exception (one that wasn't properly "
"specified\nin the throws() specifier for the throwing function)."
"\n\n");
- if(CVC4::s_debugLastException == NULL) {
+
+ const char* lastContents = LastExceptionBuffer::currentContents();
+
+ if(lastContents == NULL) {
fprintf(stderr,
"The exception is unknown (maybe it's not a CVC4::Exception).\n\n");
} else {
- fprintf(stderr, "The exception is:\n%s\n\n",
- static_cast<const char*>(CVC4::s_debugLastException));
+ fprintf(stderr, "The exception is:\n%s\n\n", lastContents);
}
if(!segvSpin) {
if((*pOptions)[options::statistics] && pExecutor != NULL) {
void cvc4terminate() {
set_terminate(default_terminator);
#ifdef CVC4_DEBUG
+ LastExceptionBuffer* current = LastExceptionBuffer::getCurrent();
+ LastExceptionBuffer::setCurrent(NULL);
+ delete current;
+
fprintf(stderr, "\n"
"CVC4 was terminated by the C++ runtime.\n"
"Perhaps an exception was thrown during stack unwinding. "
/** Initialize the driver. Sets signal handlers for SIGINT and SIGSEGV. */
void cvc4_init() throw(Exception) {
+#ifdef CVC4_DEBUG
+ LastExceptionBuffer::setCurrent(new LastExceptionBuffer());
+#endif
+
#ifndef __WIN32__
stack_t ss;
ss.ss_sp = malloc(SIGSTKSZ);