[Rcpp-devel] Passing pointers to objects between libs results in weird UBSAN warning

Jan van der Laan rhelp at eoos.dds.nl
Mon Aug 20 09:01:21 CEST 2018


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
     }

     // [[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.

So, help!?

Jan







More information about the Rcpp-devel mailing list