Oleg Sklyar
2007-Feb-13 08:55 UTC
[R] anyone has C++ STL classes stability issue if used with R
Hello, is there any one who uses C++ STL classes when programming shared libs for R and has had any problems with STL? In the very simple example below I am constantly getting segfaults when trying to populate the queue. The segfault occurs at what looks like a random index in the loop when pushing another element to the queue. Reproduced on 4 machines. Object x is an Image as in EBImage, i.e. a 3D R-array of numerics for the purpose of this code. LENGTH(x) can be up to 1e6 and the number of elements potentially to be in the queue is about 20% of those. But I get segfaults often on a third of fours element being added. Tried on R2.5.0-devel, R2.4.1-release and all machines were 64bit Linux with kernels 2.6.9 (stable CentOS), 2.6.17 (stable Ubuntu) and 2.6.20 (Ubuntu devel). Here are the compilation options of this particular module (built as part of EBImage, which generally compiles and works just fine): -------------------------------------------------------------------------- g++ -I/home/osklyar/R/R-2.5.0-40659/include -I/home/osklyar/R/R-2.5.0-40659/include -I/usr/local/include -DUSE_GTK -DGLIB_GETTEXT -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -Wall -g -O2 -Wall -pthread -I/usr/include -O2 -g -O2 -g -fpic -O2 -g -c filters_watershed.cpp -o filters_watershed.o -------------------------------------------------------------------------- And the linker: -------------------------------------------------------------------------- g++ -shared -L/usr/local/lib64 -o EBImage.so colors.o conversions.o display.o filters_distmap.o filters_magick.o filters_morph.o filters_propagate.o filters_thresh.o filters_watershed.o init.o io.o object_counting.o tools.o -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lfontconfig -lXext -lXrender -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lX11 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -L/usr/lib -L/usr/X11R6/lib -lfreetype -lz -L/usr/lib -lMagick -llcms -ltiff -lfreetype -ljasper -ljpeg -lpng -lXext -lSM -lICE -lX11 -lbz2 -lxml2 -lz -lpthread -lm -lpthread -------------------------------------------------------------------------- It could be I am missing something totally simple and therefore get these errors, but I cannot identify what. Thanks for help, Oleg ----------------------------------------- // common.h also includes R includes: // #include <R.h> // #include <Rdefines.h> // #include <R_ext/Error.h> #include "common.h" #include <queue> using namespace std; struct Pixel { int x, y; double intens; /* the code will also fail with the same segfault if I remove all * the constructors here and use the commented block below instead * of pq.push( Pixel(i, j, val) */ Pixel() {x = 0; y = 0; intens = 0; }; Pixel(const Pixel& px) { x = px.x; y = px.y; intens = px.intens; }; Pixel(int i, int j, double val): x(i), y(j), intens(val) {}; }; bool operator < (const Pixel & a, const Pixel & b) { return a.intens < b.intens; }; typedef priority_queue<Pixel> PixelPrQueue; SEXP lib_filterInvWS (SEXP x) { SEXP res; int i, j, index; double val; PixelPrQueue pq; int nx = INTEGER ( GET_DIM(x) )[0]; int ny = INTEGER ( GET_DIM(x) )[1]; int nz = INTEGER ( GET_DIM(x) )[2]; int nprotect = 0; PROTECT ( res = Rf_duplicate(x) ); nprotect++; // Pixel px; for (int im = 0; im < nz; im++ ) { double * src = &( REAL(x)[ im * nx * ny ] ); double * tgt = &( REAL(res)[ im * nx * ny ] ); for ( j = 0; j < ny; j++ ) for ( i = 0; i < nx; i++ ) { index = i + nx * j; val = src[ index ]; if ( val > BG ) { tgt[ index ] = -1; // px.x = i; px.y = j; px.intens = val; pq.push(px); pq.push( Pixel(i, j, val) ); continue; } tgt[ index ] = BG; } } /* my main code was here, but deleted for debug */ UNPROTECT (nprotect); return res; } -- Dr Oleg Sklyar * EBI/EMBL, Cambridge CB10 1SD, England * +44-1223-494466
Oleg Sklyar
2007-Feb-13 09:24 UTC
[R] anyone has C++ STL classes stability issue if used with R
Continued: With the following modifications (using pointers) it works (needs memory cleaning afterwards and new less operator though) and I do not understand why: typedef priority_queue<Pixel *> PixelPrQueue; ... pq.push( new Pixel(i, j, val) ); ... Oleg Sklyar wrote:> Hello, > > is there any one who uses C++ STL classes when programming shared libs > for R and has had any problems with STL? > > In the very simple example below I am constantly getting segfaults when > trying to populate the queue. The segfault occurs at what looks like a > random index in the loop when pushing another element to the queue. > Reproduced on 4 machines. Object x is an Image as in EBImage, i.e. a 3D > R-array of numerics for the purpose of this code. > > LENGTH(x) can be up to 1e6 and the number of elements potentially to be > in the queue is about 20% of those. But I get segfaults often on a third > of fours element being added. > > Tried on R2.5.0-devel, R2.4.1-release and all machines were 64bit Linux > with kernels 2.6.9 (stable CentOS), 2.6.17 (stable Ubuntu) and 2.6.20 > (Ubuntu devel). > > Here are the compilation options of this particular module (built as > part of EBImage, which generally compiles and works just fine): > > -------------------------------------------------------------------------- > g++ -I/home/osklyar/R/R-2.5.0-40659/include > -I/home/osklyar/R/R-2.5.0-40659/include -I/usr/local/include > -DUSE_GTK -DGLIB_GETTEXT -I/usr/include/gtk-2.0 > -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo > -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 > -I/usr/lib/glib-2.0/include -Wall -g -O2 -Wall -pthread -I/usr/include > -O2 -g -O2 -g -fpic -O2 -g -c filters_watershed.cpp -o > filters_watershed.o > -------------------------------------------------------------------------- > And the linker: > -------------------------------------------------------------------------- > g++ -shared -L/usr/local/lib64 -o EBImage.so colors.o conversions.o > display.o filters_distmap.o filters_magick.o filters_morph.o > filters_propagate.o filters_thresh.o filters_watershed.o init.o io.o > object_counting.o tools.o -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 > -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lfontconfig -lXext -lXrender > -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lX11 > -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -L/usr/lib > -L/usr/X11R6/lib -lfreetype -lz -L/usr/lib -lMagick -llcms -ltiff > -lfreetype -ljasper -ljpeg -lpng -lXext -lSM -lICE -lX11 -lbz2 -lxml2 > -lz -lpthread -lm -lpthread > -------------------------------------------------------------------------- > > It could be I am missing something totally simple and therefore get > these errors, but I cannot identify what. > > Thanks for help, > Oleg > > ----------------------------------------- > // common.h also includes R includes: > // #include <R.h> > // #include <Rdefines.h> > // #include <R_ext/Error.h> > > #include "common.h" > > #include <queue> > > using namespace std; > > struct Pixel { > int x, y; > double intens; > /* the code will also fail with the same segfault if I remove all > * the constructors here and use the commented block below instead > * of pq.push( Pixel(i, j, val) */ > Pixel() {x = 0; y = 0; intens = 0; }; > Pixel(const Pixel& px) { x = px.x; y = px.y; intens = px.intens; }; > Pixel(int i, int j, double val): x(i), y(j), intens(val) {}; > }; > > bool operator < (const Pixel & a, const Pixel & b) { > return a.intens < b.intens; > }; > > typedef priority_queue<Pixel> PixelPrQueue; > > SEXP > lib_filterInvWS (SEXP x) { > SEXP res; > int i, j, index; > double val; > PixelPrQueue pq; > > int nx = INTEGER ( GET_DIM(x) )[0]; > int ny = INTEGER ( GET_DIM(x) )[1]; > int nz = INTEGER ( GET_DIM(x) )[2]; > int nprotect = 0; > > PROTECT ( res = Rf_duplicate(x) ); > nprotect++; > > // Pixel px; > for (int im = 0; im < nz; im++ ) { > double * src = &( REAL(x)[ im * nx * ny ] ); > double * tgt = &( REAL(res)[ im * nx * ny ] ); > > for ( j = 0; j < ny; j++ ) > for ( i = 0; i < nx; i++ ) { > index = i + nx * j; > val = src[ index ]; > if ( val > BG ) { > tgt[ index ] = -1; > // px.x = i; px.y = j; px.intens = val; pq.push(px); > pq.push( Pixel(i, j, val) ); > continue; > } > tgt[ index ] = BG; > } > } > > /* my main code was here, but deleted for debug */ > > UNPROTECT (nprotect); > return res; > } > > > >-- Dr Oleg Sklyar * EBI/EMBL, Cambridge CB10 1SD, England * +44-1223-494466
Duncan Murdoch
2007-Feb-13 12:14 UTC
[R] anyone has C++ STL classes stability issue if used with R
On 2/13/2007 3:55 AM, Oleg Sklyar wrote:> Hello, > > is there any one who uses C++ STL classes when programming shared libs > for R and has had any problems with STL?I don't, but I'd suggest asking a technical question like this on R-devel instead of R-help if you don't get help here. I can see a few probably innocuous changes I'd suggest in your code below, but nothing obvious: use Rinternals.h instead of Rdefines.h, don't use the Rf_ prefix, check the length of inputs before working with the values. Duncan Murdoch> > In the very simple example below I am constantly getting segfaults when > trying to populate the queue. The segfault occurs at what looks like a > random index in the loop when pushing another element to the queue. > Reproduced on 4 machines. Object x is an Image as in EBImage, i.e. a 3D > R-array of numerics for the purpose of this code. > > LENGTH(x) can be up to 1e6 and the number of elements potentially to be > in the queue is about 20% of those. But I get segfaults often on a third > of fours element being added. > > Tried on R2.5.0-devel, R2.4.1-release and all machines were 64bit Linux > with kernels 2.6.9 (stable CentOS), 2.6.17 (stable Ubuntu) and 2.6.20 > (Ubuntu devel). > > Here are the compilation options of this particular module (built as > part of EBImage, which generally compiles and works just fine): > > -------------------------------------------------------------------------- > g++ -I/home/osklyar/R/R-2.5.0-40659/include > -I/home/osklyar/R/R-2.5.0-40659/include -I/usr/local/include > -DUSE_GTK -DGLIB_GETTEXT -I/usr/include/gtk-2.0 > -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo > -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 > -I/usr/lib/glib-2.0/include -Wall -g -O2 -Wall -pthread -I/usr/include > -O2 -g -O2 -g -fpic -O2 -g -c filters_watershed.cpp -o > filters_watershed.o > -------------------------------------------------------------------------- > And the linker: > -------------------------------------------------------------------------- > g++ -shared -L/usr/local/lib64 -o EBImage.so colors.o conversions.o > display.o filters_distmap.o filters_magick.o filters_morph.o > filters_propagate.o filters_thresh.o filters_watershed.o init.o io.o > object_counting.o tools.o -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 > -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lfontconfig -lXext -lXrender > -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lX11 > -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -L/usr/lib > -L/usr/X11R6/lib -lfreetype -lz -L/usr/lib -lMagick -llcms -ltiff > -lfreetype -ljasper -ljpeg -lpng -lXext -lSM -lICE -lX11 -lbz2 -lxml2 > -lz -lpthread -lm -lpthread > -------------------------------------------------------------------------- > > It could be I am missing something totally simple and therefore get > these errors, but I cannot identify what. > > Thanks for help, > Oleg > > ----------------------------------------- > // common.h also includes R includes: > // #include <R.h> > // #include <Rdefines.h> > // #include <R_ext/Error.h> > > #include "common.h" > > #include <queue> > > using namespace std; > > struct Pixel { > int x, y; > double intens; > /* the code will also fail with the same segfault if I remove all > * the constructors here and use the commented block below instead > * of pq.push( Pixel(i, j, val) */ > Pixel() {x = 0; y = 0; intens = 0; }; > Pixel(const Pixel& px) { x = px.x; y = px.y; intens = px.intens; }; > Pixel(int i, int j, double val): x(i), y(j), intens(val) {}; > }; > > bool operator < (const Pixel & a, const Pixel & b) { > return a.intens < b.intens; > }; > > typedef priority_queue<Pixel> PixelPrQueue; > > SEXP > lib_filterInvWS (SEXP x) { > SEXP res; > int i, j, index; > double val; > PixelPrQueue pq; > > int nx = INTEGER ( GET_DIM(x) )[0]; > int ny = INTEGER ( GET_DIM(x) )[1]; > int nz = INTEGER ( GET_DIM(x) )[2]; > int nprotect = 0; > > PROTECT ( res = Rf_duplicate(x) ); > nprotect++; > > // Pixel px; > for (int im = 0; im < nz; im++ ) { > double * src = &( REAL(x)[ im * nx * ny ] ); > double * tgt = &( REAL(res)[ im * nx * ny ] ); > > for ( j = 0; j < ny; j++ ) > for ( i = 0; i < nx; i++ ) { > index = i + nx * j; > val = src[ index ]; > if ( val > BG ) { > tgt[ index ] = -1; > // px.x = i; px.y = j; px.intens = val; pq.push(px); > pq.push( Pixel(i, j, val) ); > continue; > } > tgt[ index ] = BG; > } > } > > /* my main code was here, but deleted for debug */ > > UNPROTECT (nprotect); > return res; > } > > > >