On 20 August 2018 at 15:35, Iñaki Ucar wrote: | El lun., 20 ago. 2018 a las 9:01, Jan van der Laan | (<rh...@eoos.dds.nl>) escribió: | > | > | > One of my packges gives a message with the undefined behaviour sanitiser | > (UBSAN). I have difficulty tracking down/understanding the cause of this | > message. However, I have been able to create a small example that | > generates the same warning. The mail below is a bit on the long side, | > and, I hope it is readable as it mixes quite a lot code with text. I am | > sorry for that. A probably better readable version can be found at | > https://github.com/djvanderlaan/lvec_ubsan where also the complete | > source code and the docker image used for testing can be found. | > | > My example consists of two packages: pkg1 and pkg2. The package pkg2 | > links to pkg1. Package pkg1 defines a template class `FooBar<T>` which | > inherits from virtual class `Foo`. Pointers to the these objects are | > passed back to R using a `Rcpp:XPtr` object: | > | > ========== pkg1/src/construct.cpp ================ | > #include "../inst/include/pkg1.h" | > | > // [[Rcpp::export]] | > RcppExport SEXP new_foobar(int i) { | > BEGIN_RCPP | > FooBar<int>* x = new FooBar<int>(i); | > return Rcpp::XPtr<Foo>(x, true); | > END_RCPP | > } | | Note that RcppExport SEXP should be just SEXP. BEGIN_RCPP and END_RCPP | should be dropped too.
+1 Or else don't use [[Rcpp::export]] and Rcpp::compileAttributes(). Dirk | > // [[Rcpp::export]] | > RcppExport SEXP new_foobard(double i) { | > BEGIN_RCPP | > FooBar<double>* x = new FooBar<double>(i); | > return Rcpp::XPtr<Foo>(x, true); | > END_RCPP | > } | > ========== END pkg1/src/construct.cpp ================ | > | > All headers of pkg1 are `inst/include`; these are included by `pkg2`: | > | > ========== pkg1/inst/include/pkg1.h ================ | > #include <Rcpp.h> | > | > // ==== VISITOR | > template<typename T> class FooBar; | > | > class FooBarVisitor { | > public: | > virtual void visit(FooBar<double>& vec) = 0; | > virtual void visit(FooBar<int>& vec) = 0; | > }; | > | > // ==== FOO | > class Foo { | > public: | > Foo() {}; | > virtual ~Foo() {}; | > | > virtual void visit(FooBarVisitor* visitor) = 0; | > }; | > | > // ==== FOOBAR | > template<typename T> | > class FooBar : public Foo { | > public: | > FooBar(T i = 0) : Foo(), i_(i) {}; | > ~FooBar() {}; | > | > T i() const { return i_;} | > void i(T i) { i_ = i;} | > | > void visit(FooBarVisitor* visitor) { | > visitor->visit(*this); | > } | > private: | > T i_; | > }; | > #endif | > ========== END pkg1/inst/include/pkg1.h ================ | > | > The XPtr is passed to c++ code in pkg2 and methods of the Foo object are | > called: | > | > ========== pkg2/src/construct.cpp ================ | > #include <Rcpp.h> | > #include <pkg1.h> | > | > // [[Rcpp::export]] | > RcppExport int get_foobar(SEXP xp) { | > Rcpp::XPtr<Foo> x(xp); | > Foo* y1 = x; | > FooBar<int>* y2 = dynamic_cast<FooBar<int>*>(y1); | > return y2->i(); | > } | > ========== END pkg2/src/construct.cpp ================ | > | > This generates the following UBSAN messages: | > | > | > ========== WARNING MESSAGES ================ | > Testing pkg2 | > <U+221A> | OK F W S | Context | > / | 0 | fooconstruct.cpp:9:21: runtime error: <null> address | > 0x000003c21810 which does not point to an object of type 'Foo' | > 0x000003c21810: note: object is of type 'FooBar<int>' | > 00 00 00 00 58 1c 79 fd 48 7f 00 00 0a 00 00 00 00 00 00 00 20 | > 00 00 00 00 00 00 00 01 03 00 00 | > ^~~~~~~~~~~~~~~~~~~~~~~ | > vptr for 'FooBar<int>' | > construct.cpp:10:14: runtime error: member call on address | > 0x000003c21810 which does not point to an object of type 'FooBar<int>' | > 0x000003c21810: note: object is of type 'FooBar<int>' | > 00 00 00 00 58 1c 79 fd 48 7f 00 00 0a 00 00 00 00 00 00 00 20 | > 00 00 00 00 00 00 00 01 03 00 00 | > ^~~~~~~~~~~~~~~~~~~~~~~ | > vptr for 'FooBar<int>' | > /usr/local/lib/R/library/pkg1/include/pkg1.h:33:26: runtime error: | > member access within address 0x000003c21810 which does not point to an | > object of type 'const FooBar<int>' | > 0x000003c21810: note: object is of type 'FooBar<int>' | > 00 00 00 00 58 1c 79 fd 48 7f 00 00 0a 00 00 00 00 00 00 00 20 | > 00 00 00 00 00 00 00 01 03 00 00 | > ^~~~~~~~~~~~~~~~~~~~~~~ | > vptr for 'FooBar<int>' | > <U+221A> | 1 | foo | > ========== END WARNING MESSAGES ================ | > | > | > I have had real problem reproducing this error. Also searching for the | > error give little clues as to what the problem is. The following message | > on the Rcpp-devel list seems somewhat similar: | > http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2017-July/009656.html. | > I thought that it might be caused by the fact that I am passing pointers | > to template classes between libraries. I also couldn't find much about | > that. I did find some messages on passing pointers to STL objects | > between libraries. That should be ok, as long as the same compiler is | > used for both libraries. Although that might technically still make it | > undefined behaviour. | | pkg2 compiles a shared library using pkg1's headers, but it does not | link against libpkg1.so (in general, this is not possible in R). So | both libpkg2.so and libpkg1.so define two copies of the same types, | Foo and FooBar. pkg2 allocates FooBar from libpkg1.so and then | dynamically casts it as FooBar from libpkg2.so. This is why clang | complains. It has to do with how RTTI comparisons are done across | dynamic objects (see, e.g., | https://whatofhow.wordpress.com/2015/03/17/odr-rtti-dso/). | | I'd say that these errors can be safely ignored, because types are | exactly the same. Anyway, shouldn't it be easier to export get_foobar | in pkg1? The only thought I had so far (and I had no time to play with the code) is to maybe wrap Rcpp::Shield<> around the XPtr object. Dirk | | Iñaki | | > | > So, help!? | > | > Jan | > | > | > | > | > | > _______________________________________________ | > Rcpp-devel mailing list | > Rcpp-devel@lists.r-forge.r-project.org | > https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel | | | | -- | Iñaki Ucar | _______________________________________________ | Rcpp-devel mailing list | Rcpp-devel@lists.r-forge.r-project.org | https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel -- http://dirk.eddelbuettel.com | @eddelbuettel | e...@debian.org _______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel