From 95e7eea4b77cd5aa780cad2a999aa33519d968fe Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Mon, 18 May 2020 02:19:54 -0400 Subject: [PATCH 1/6] Demangle the type when printing --- gtsam/base/GenericValue.h | 29 ++++++++++++++++++++++++++++- gtsam/nonlinear/Values.cpp | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/gtsam/base/GenericValue.h b/gtsam/base/GenericValue.h index aee6c0e62..b4a74913b 100644 --- a/gtsam/base/GenericValue.h +++ b/gtsam/base/GenericValue.h @@ -31,6 +31,33 @@ namespace gtsam { +#ifdef __GNUG__ +#include +#include +#include + +/// Pretty print Value type name +static std::string demangle(const char* name) { + int status = -4; // some arbitrary value to eliminate the compiler warning + // enable c++11 by passing the flag -std=c++11 to g++ + std::unique_ptr res { + abi::__cxa_demangle(name, NULL, NULL, &status), + std::free + }; + return (status==0) ? res.get() : name ; +} + +#else + +// does nothing if not g++ +static std::string demangle(const char* name) { + return name; +} + +#endif + + + /** * Wraps any type T so it can play as a Value */ @@ -83,7 +110,7 @@ public: /// Virtual print function, uses traits virtual void print(const std::string& str) const { - std::cout << "(" << typeid(T).name() << ") "; + std::cout << "(" << demangle(typeid(T).name()) << ") "; traits::Print(value_, str); } diff --git a/gtsam/nonlinear/Values.cpp b/gtsam/nonlinear/Values.cpp index 1bd8b3a73..c5a7c8c32 100644 --- a/gtsam/nonlinear/Values.cpp +++ b/gtsam/nonlinear/Values.cpp @@ -235,7 +235,7 @@ namespace gtsam { if(message_.empty()) message_ = "Attempting to retrieve value with key \"" + DefaultKeyFormatter(key_) + "\", type stored in Values is " + - std::string(storedTypeId_.name()) + " but requested type was " + std::string(requestedTypeId_.name()); + std::string(demangle(storedTypeId_.name())) + " but requested type was " + std::string(demangle(requestedTypeId_.name())); return message_.c_str(); } From d05279ee5e3021b1d7e88a0fec446520adc55e24 Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Mon, 18 May 2020 16:39:03 -0500 Subject: [PATCH 2/6] updated demangle code to not use unique_ptr, support for Windows, and a simple test --- gtsam/base/GenericValue.h | 28 +----------- gtsam/base/types.cpp | 68 ++++++++++++++++++++++++++++ gtsam/base/types.h | 3 ++ gtsam/nonlinear/tests/testValues.cpp | 17 +++++++ 4 files changed, 89 insertions(+), 27 deletions(-) create mode 100644 gtsam/base/types.cpp diff --git a/gtsam/base/GenericValue.h b/gtsam/base/GenericValue.h index b4a74913b..e1cb3bc2c 100644 --- a/gtsam/base/GenericValue.h +++ b/gtsam/base/GenericValue.h @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include @@ -31,33 +32,6 @@ namespace gtsam { -#ifdef __GNUG__ -#include -#include -#include - -/// Pretty print Value type name -static std::string demangle(const char* name) { - int status = -4; // some arbitrary value to eliminate the compiler warning - // enable c++11 by passing the flag -std=c++11 to g++ - std::unique_ptr res { - abi::__cxa_demangle(name, NULL, NULL, &status), - std::free - }; - return (status==0) ? res.get() : name ; -} - -#else - -// does nothing if not g++ -static std::string demangle(const char* name) { - return name; -} - -#endif - - - /** * Wraps any type T so it can play as a Value */ diff --git a/gtsam/base/types.cpp b/gtsam/base/types.cpp new file mode 100644 index 000000000..827d71cd6 --- /dev/null +++ b/gtsam/base/types.cpp @@ -0,0 +1,68 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file types.cpp + * @brief Functions for handling type information + * @author Varun Agrawal + * @date May 18, 2020 + * @addtogroup base + */ + +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +#ifdef __GNUG__ +#include +#include +#include +#endif + +namespace gtsam { + +/// Pretty print Value type name +std::string demangle(const char* name) { + // by default set to the original mangled name + std::string demangled_name = std::string(name); + +#ifdef __GNUG__ + // g++ version of demangle + char* demangled = nullptr; + int status = -1; // some arbitrary value to eliminate the compiler warning + demangled = abi::__cxa_demangle(name, nullptr, nullptr, &status), + + demangled_name = (status == 0) ? std::string(demangled) : name; + + std::free(demangled); + +#endif +#ifdef _WIN32 + char undecorated_name[1024]; + + if (UnDecorateSymbolName( + name, undecorated_name, sizeof(undecorated_name), + UNDNAME_COMPLETE)) + { + // successful conversion, take value from: undecorated_name + demangled_name = std::string(undecorated_name); + } + // else keep using mangled name +#endif + + return demangled_name; +} + +} /* namespace gtsam */ diff --git a/gtsam/base/types.h b/gtsam/base/types.h index d12a4209a..2fa6eebb6 100644 --- a/gtsam/base/types.h +++ b/gtsam/base/types.h @@ -53,6 +53,9 @@ namespace gtsam { + /// Function to demangle type name of variable, e.g. demangle(typeid(x).name()) + std::string demangle(const char* name); + /// Integer nonlinear key type typedef std::uint64_t Key; diff --git a/gtsam/nonlinear/tests/testValues.cpp b/gtsam/nonlinear/tests/testValues.cpp index b8eee540d..2f624f527 100644 --- a/gtsam/nonlinear/tests/testValues.cpp +++ b/gtsam/nonlinear/tests/testValues.cpp @@ -589,6 +589,23 @@ TEST(Values, MatrixDynamicInsertFixedRead) { CHECK_EXCEPTION(values.at(key1), exception); } +TEST(Values, Demangle) { + Values values; + Matrix13 v; v << 5.0, 6.0, 7.0; + values.insert(key1, v); + string expected = "Values with 1 values:\nValue v1: (Eigen::Matrix) [\n 5, 6, 7\n]\n\n"; + + stringstream buffer; + streambuf * old = cout.rdbuf(buffer.rdbuf()); + + values.print(); + + string actual = buffer.str(); + cout.rdbuf(old); + + EXPECT(assert_equal(expected, actual)); +} + /* ************************************************************************* */ int main() { TestResult tr; return TestRegistry::runAllTests(tr); } /* ************************************************************************* */ From 25bf695b771c21f1ec0c5b8929405db6518dde15 Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Mon, 18 May 2020 16:43:14 -0500 Subject: [PATCH 3/6] updated cmake to include library for Windows demangling --- gtsam/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gtsam/CMakeLists.txt b/gtsam/CMakeLists.txt index 1079b845f..cabd5e402 100644 --- a/gtsam/CMakeLists.txt +++ b/gtsam/CMakeLists.txt @@ -172,6 +172,10 @@ if(WIN32) # Add 'lib' prefix to static library to avoid filename collision with endif() endif() +if(WIN32) # library to help with demangling variable names on Windows + target_link_libraries(gtsam PRIVATE Dbghelp) +endif() + install( TARGETS gtsam EXPORT GTSAM-exports From 77ffbf47cc6082448fbd972c350a24b814c909a3 Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Mon, 18 May 2020 17:37:02 -0500 Subject: [PATCH 4/6] better conditional compilation --- gtsam/base/types.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gtsam/base/types.cpp b/gtsam/base/types.cpp index 827d71cd6..817d697b2 100644 --- a/gtsam/base/types.cpp +++ b/gtsam/base/types.cpp @@ -48,8 +48,7 @@ std::string demangle(const char* name) { std::free(demangled); -#endif -#ifdef _WIN32 +#elif _WIN32 char undecorated_name[1024]; if (UnDecorateSymbolName( From baaa656628218646fe469522290204cf542ff83b Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Mon, 18 May 2020 17:45:45 -0500 Subject: [PATCH 5/6] demangle other type instances --- gtsam/nonlinear/internal/ExpressionNode.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gtsam/nonlinear/internal/ExpressionNode.h b/gtsam/nonlinear/internal/ExpressionNode.h index 6752d7fc0..0011efb74 100644 --- a/gtsam/nonlinear/internal/ExpressionNode.h +++ b/gtsam/nonlinear/internal/ExpressionNode.h @@ -84,7 +84,7 @@ public: /// Streaming GTSAM_EXPORT friend std::ostream& operator<<(std::ostream& os, const ExpressionNode& node) { - os << "Expression of type " << typeid(T).name(); + os << "Expression of type " << demangle(typeid(T).name()); if (node.traceSize_ > 0) os << ", trace size = " << node.traceSize_; os << "\n"; return os; @@ -219,7 +219,7 @@ static void PrintJacobianAndTrace(const std::string& indent, const typename Jacobian::type& dTdA, const ExecutionTrace trace) { static const Eigen::IOFormat kMatlabFormat(0, 1, " ", "; ", "", "", "[", "]"); - std::cout << indent << "D(" << typeid(T).name() << ")/D(" << typeid(A).name() + std::cout << indent << "D(" << demangle(typeid(T).name()) << ")/D(" << demangle(typeid(A).name()) << ") = " << dTdA.format(kMatlabFormat) << std::endl; trace.print(indent); } @@ -605,7 +605,7 @@ class ScalarMultiplyNode : public ExpressionNode { /// Print to std::cout void print(const std::string& indent) const { std::cout << indent << "ScalarMultiplyNode::Record {" << std::endl; - std::cout << indent << "D(" << typeid(T).name() << ")/D(" << typeid(T).name() + std::cout << indent << "D(" << demangle(typeid(T).name()) << ")/D(" << demangle(typeid(T).name()) << ") = " << scalar_dTdA << std::endl; trace.print(); std::cout << indent << "}" << std::endl; From 14ccd06bf2dc467517954ea12ef8d0e17abb5383 Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Tue, 19 May 2020 17:34:07 -0500 Subject: [PATCH 6/6] print custom error message if type names match --- gtsam/base/types.cpp | 2 +- gtsam/nonlinear/Values.cpp | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/gtsam/base/types.cpp b/gtsam/base/types.cpp index 817d697b2..edc449b12 100644 --- a/gtsam/base/types.cpp +++ b/gtsam/base/types.cpp @@ -44,7 +44,7 @@ std::string demangle(const char* name) { int status = -1; // some arbitrary value to eliminate the compiler warning demangled = abi::__cxa_demangle(name, nullptr, nullptr, &status), - demangled_name = (status == 0) ? std::string(demangled) : name; + demangled_name = (status == 0) ? std::string(demangled) : std::string(name); std::free(demangled); diff --git a/gtsam/nonlinear/Values.cpp b/gtsam/nonlinear/Values.cpp index c5a7c8c32..98790ccd9 100644 --- a/gtsam/nonlinear/Values.cpp +++ b/gtsam/nonlinear/Values.cpp @@ -232,10 +232,21 @@ namespace gtsam { /* ************************************************************************* */ const char* ValuesIncorrectType::what() const throw() { - if(message_.empty()) - message_ = - "Attempting to retrieve value with key \"" + DefaultKeyFormatter(key_) + "\", type stored in Values is " + - std::string(demangle(storedTypeId_.name())) + " but requested type was " + std::string(demangle(requestedTypeId_.name())); + if(message_.empty()) { + std::string storedTypeName = demangle(storedTypeId_.name()); + std::string requestedTypeName = demangle(requestedTypeId_.name()); + + if (storedTypeName == requestedTypeName) { + message_ = "WARNING: Detected types with same name but different `typeid`. \ + This is usually caused by incorrect linking/inlining settings when compiling libraries using GTSAM. \ + If you are a user, please report to the author of the library using GTSAM. \ + If you are a package maintainer, please consult `cmake/GtsamPybindWrap.cmake`, line 74 for details."; + } else { + message_ = + "Attempting to retrieve value with key \"" + DefaultKeyFormatter(key_) + "\", type stored in Values is " + + storedTypeName + " but requested type was " + requestedTypeName; + } + } return message_.c_str(); }