Skip to content

[Rcpp-devel] Using C++0x in g++ changes ifelse behaviour

6 messages · Darren Cook, Dirk Eddelbuettel, Douglas Bates

#
I posted this on StackOverflow yesterday, but maybe of more interest to
people here:
  How to set g++ compiler flags using Rcpp and inline?
  http://stackoverflow.com/q/7063265/841830

In lieu of an answer I created ~/.R/Makevars with this single line:
  CXXFLAGS = -std=c++0x

That works, but then I realized that ifelse is behaving differently today!

This simple example I posted yesterday:
  using namespace Rcpp;
  NumericMatrix x(x_);
  return wrap(ifelse(x<5,x*x,x));

returned this before:
  1  4  9 16  5  6  7  8  9 10 11 12

but in c++0x mode (g++ 3.4) it returns:
  0  0  0  0  5  6  7  8  9 10 11 12

Then, Christopher's reply [1] works with normal g++, but crashes with
c++0x mode (see [2] for the error). As I played around with the code I
sometimes got garbage values in the returned matrix instead of a crash.
(-std=gnu++0x behaves the same.)

I took a look at the Rcpp source and the only thing that came to mind is
that exception specifications have been deprecated but the Rcpp code is
using them everywhere. I don't see how that could explain the observed
behaviour though, so I think it must be something more obscure?

Does everyone see the problem with different C++0x compilers, and/or
later versions of g++?

Darren


[1]:
using namespace Rcpp;
NumericMatrix x(x_);
NumericVector y=ifelse(x<5,x*x,x);
y.attr("dim")=Dimension(x.nrow(),x.ncol());
return y;

[2]:
 *** caught segfault ***
address 0x300000000, cause 'memory not mapped'

Traceback:
 1: .Primitive(".Call")(<pointer: 0x7f36acb327e6>, x_)
 2: fun(x)
 3: print(fun(x))
 4: eval.with.vis(expr, envir, enclos)
 5: eval.with.vis(ei, envir)
 6: source("test4.R")
#
Hi Darren,
On 16 August 2011 at 11:10, Darren Cook wrote:
| I posted this on StackOverflow yesterday, but maybe of more interest to
| people here:
|   How to set g++ compiler flags using Rcpp and inline?
|   http://stackoverflow.com/q/7063265/841830
| 
| In lieu of an answer I created ~/.R/Makevars with this single line:
|   CXXFLAGS = -std=c++0x
| 
| That works, but then I realized that ifelse is behaving differently today!
| 
| This simple example I posted yesterday:
|   using namespace Rcpp;
|   NumericMatrix x(x_);
|   return wrap(ifelse(x<5,x*x,x));
| 
| returned this before:
|   1  4  9 16  5  6  7  8  9 10 11 12
| 
| but in c++0x mode (g++ 3.4) it returns:
|   0  0  0  0  5  6  7  8  9 10 11 12

I just tried and could _not_ replicate it. I just uncommented my standard
line with the flag in ~/.R/Makevars:

CXXFLAGS= -std=c++0x -g -O3 -Wall -pipe -pedantic -Wno-variadic-macros 

I am using g++-4.5:

R> foo2 <- cxxfunction(signature(x_ ="numeric", y_ ="numeric"), plugin="Rcpp", verbose=TRUE, body='
+   NumericVector x(x_),y(y_);
+   return Rcpp::wrap(ifelse( x<y, x*x, -(y*y) ));
+   ')
 >> setting environment variables: 
PKG_LIBS =  -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib

 >> LinkingTo : Rcpp
CLINK_CPPFLAGS =  -I"/usr/local/lib/R/site-library/Rcpp/include" 

 >> Program source :

   1 : 
   2 : // includes from the plugin
   3 : 
   4 : #include <Rcpp.h>
   5 : 
   6 : 
   7 : #ifndef BEGIN_RCPP
   8 : #define BEGIN_RCPP
   9 : #endif
  10 : 
  11 : #ifndef END_RCPP
  12 : #define END_RCPP
  13 : #endif
  14 : 
  15 : using namespace Rcpp;
  16 : 
  17 : 
  18 : 
  19 : // user includes
  20 : 
  21 : 
  22 : // declarations
  23 : extern "C" {
  24 : SEXP file68831c26( SEXP x_, SEXP y_) ;
  25 : }
  26 : 
  27 : // definition
  28 : 
  29 : SEXP file68831c26( SEXP x_, SEXP y_ ){
  30 : BEGIN_RCPP
  31 : 
  32 :   NumericVector x(x_),y(y_);
  33 :   return Rcpp::wrap(ifelse( x<y, x*x, -(y*y) ));
  34 :   
  35 : END_RCPP
  36 : }
  37 : 
  38 : 
Compilation argument:
 /usr/lib64/R/bin/R CMD SHLIB file68831c26.cpp 2> file68831c26.cpp.err.txt 
ccache g++-4.5 -I/usr/share/R/include   -I"/usr/local/lib/R/site-library/Rcpp/include"   -fpic  -std=c++0x -g -O3 -Wall -pipe -pedantic -Wno-variadic-macros  -c file68831c26.cpp -o file68831c26.o
g++ -shared -o file68831c26.so file68831c26.o -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR
R> x <- c(1:12)
R> y <- c(4:15)
R> foo2(x, y)
 [1]   1   4   9  16  25  36  49  64  81 100 121 144
R> 

Can you pretty please try to send fully reproduceable example, including
compiler versions and flags?

| Then, Christopher's reply [1] works with normal g++, but crashes with
| c++0x mode (see [2] for the error). As I played around with the code I
| sometimes got garbage values in the returned matrix instead of a crash.
| (-std=gnu++0x behaves the same.)

Again, works here.  Standard Ubuntu 11.04, amd64 variant.

R> foo4 <- cxxfunction(signature(x_ ="numeric"), plugin="Rcpp", verbose=TRUE, body='
+   using namespace Rcpp;
+   NumericMatrix x(x_);
+   NumericVector y=ifelse(x<5,x*x,x);
+   y.attr("dim")=Dimension(x.nrow(),x.ncol());
+   return y;
+ ')
 >> setting environment variables: 
PKG_LIBS =  -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib

 >> LinkingTo : Rcpp
CLINK_CPPFLAGS =  -I"/usr/local/lib/R/site-library/Rcpp/include" 

 >> Program source :

   1 : 
   2 : // includes from the plugin
   3 : 
   4 : #include <Rcpp.h>
   5 : 
   6 : 
   7 : #ifndef BEGIN_RCPP
   8 : #define BEGIN_RCPP
   9 : #endif
  10 : 
  11 : #ifndef END_RCPP
  12 : #define END_RCPP
  13 : #endif
  14 : 
  15 : using namespace Rcpp;
  16 : 
  17 : 
  18 : 
  19 : // user includes
  20 : 
  21 : 
  22 : // declarations
  23 : extern "C" {
  24 : SEXP file51a637ef( SEXP x_) ;
  25 : }
  26 : 
  27 : // definition
  28 : 
  29 : SEXP file51a637ef( SEXP x_ ){
  30 : BEGIN_RCPP
  31 : 
  32 :   using namespace Rcpp;
  33 :   NumericMatrix x(x_);
  34 :   NumericVector y=ifelse(x<5,x*x,x);
  35 :   y.attr("dim")=Dimension(x.nrow(),x.ncol());
  36 :   return y;
  37 : 
  38 : END_RCPP
  39 : }
  40 : 
  41 : 
Compilation argument:
 /usr/lib64/R/bin/R CMD SHLIB file51a637ef.cpp 2> file51a637ef.cpp.err.txt 
ccache g++-4.5 -I/usr/share/R/include   -I"/usr/local/lib/R/site-library/Rcpp/include"   -fpic  -std=c++0x -g -O3 -Wall -pipe -pedantic -Wno-variadic-macros  -c file51a637ef.cpp -o file51a637ef.o
g++ -shared -o file51a637ef.so file51a637ef.o -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR
R> foo4(matrix(1:12,4,3))
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    4    6   10
[3,]    9    7   11
[4,]   16    8   12
R> 

 
| I took a look at the Rcpp source and the only thing that came to mind is
| that exception specifications have been deprecated but the Rcpp code is
| using them everywhere. I don't see how that could explain the observed
| behaviour though, so I think it must be something more obscure?
| 
| Does everyone see the problem with different C++0x compilers, and/or
| later versions of g++?

-std=c++0x is not that all that well tested. We used it early, but CRAN
slapped our wrist as "it is not portable". So we don't use it much yet, but
do look forward to wider C++11 support in coming years.

Dirk

 
| Darren
| 
| 
| [1]:
| using namespace Rcpp;
| NumericMatrix x(x_);
| NumericVector y=ifelse(x<5,x*x,x);
| y.attr("dim")=Dimension(x.nrow(),x.ncol());
| return y;
| 
| [2]:
|  *** caught segfault ***
| address 0x300000000, cause 'memory not mapped'
| 
| Traceback:
|  1: .Primitive(".Call")(<pointer: 0x7f36acb327e6>, x_)
|  2: fun(x)
|  3: print(fun(x))
|  4: eval.with.vis(expr, envir, enclos)
|  5: eval.with.vis(ei, envir)
|  6: source("test4.R")
| 
| -- 
| Darren Cook, Software Researcher/Developer
| 
| http://dcook.org/work/ (About me and my work)
| http://dcook.org/blogs.html (My blogs and articles)
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
#
Thanks Dirk.
I tried with your line and it works for me too. So I tried shortening it
and this works:
  CXXFLAGS= -std=c++0x -g -O3

but this does not:
  CXXFLAGS= -std=c++0x -g

This also does not work:
  CXXFLAGS= -std=c++0x -g -Wall -pipe -pedantic -Wno-variadic-macros

And neither does this:
  CXXFLAGS= -g -Wall -pipe -pedantic -Wno-variadic-macros

I.e. c++0x was a red herring, and the lack of -O3 is the problem. It
works with -O3, -O2, -O1 and -Os, but fails to work with -O0.

Very curious. I considered trying each of the individual optimization
flags [1], to narrow it down further, until I realized how many of them
there were.

Darren

[1]: http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
#
On 16 August 2011 at 12:02, Darren Cook wrote:
| > I just tried and could _not_ replicate it. I just uncommented my standard
| > line with the flag in ~/.R/Makevars:
| > 
| > CXXFLAGS= -std=c++0x -g -O3 -Wall -pipe -pedantic -Wno-variadic-macros 
| 
| Thanks Dirk.
| I tried with your line and it works for me too. So I tried shortening it
| and this works:
|   CXXFLAGS= -std=c++0x -g -O3
| 
| but this does not:
|   CXXFLAGS= -std=c++0x -g
| 
| This also does not work:
|   CXXFLAGS= -std=c++0x -g -Wall -pipe -pedantic -Wno-variadic-macros
| 
| And neither does this:
|   CXXFLAGS= -g -Wall -pipe -pedantic -Wno-variadic-macros
| 
| I.e. c++0x was a red herring, and the lack of -O3 is the problem. It
| works with -O3, -O2, -O1 and -Os, but fails to work with -O0.

Thanks for doing that. In the 15+ years of Debian maintainership I have seen
similar stuff on occassion (esp years when gfortran was newer), but the
gcc/g++ are so swamped that I never heard back fromn bug reports.  They do
have their system for submitting stuff so maybe you could distill something
that wouldn't require R and Rcpp?

Dirk
 
| Very curious. I considered trying each of the individual optimization
| flags [1], to narrow it down further, until I realized how many of them
| there were.
| 
| Darren
| 
| [1]: http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
| 
| 
| -- 
| Darren Cook, Software Researcher/Developer
| 
| http://dcook.org/work/ (About me and my work)
| http://dcook.org/blogs.html (My blogs and articles)
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
#
On Tue, Aug 16, 2011 at 4:02 AM, Darren Cook <darren at dcook.org> wrote:
We had an earlier instance of something like this.  The RcppArmadillo
package defines a struct containing the version information on
Armadillo.  For some reason it is not accessible and the link step
fails with -O0.  With optimization everything is fine.  Most peculiar
indeed.
7 days later
#
I've worked out, and added an answer to the above. In a nutshell, set
settings$env$PKG_CXXFLAGS, where settings is the return of
getPlugin("Rcpp").

(I set the answer as "community wiki", so others can enhance the answer
if they wish.)

Darren