[R] anyone has C++ STL classes stability issue if used with R
Oleg Sklyar
osklyar at ebi.ac.uk
Tue Feb 13 14:06:16 CET 2007
Duncan,
you are right about Rf_..., otherwise the lengths are checked in the R
side, this is just one of the functions I have in the package and all
arguments are thoroughly checked.
But apparently, the same code if redefined for using pointers instead of
references works just perfectly fine (given below). And I do not see why
the one I posted before fails. I will try to run it outside of R to see
if the issue is anyhow connected to R.
// comparison operator redefined for pointers:
struct Pixel_compare: public binary_function<Pixel*, Pixel*, bool> {
bool operator() (Pixel* a, Pixel* b) {
return a->intens < b->intens;
}
};
// was:
// struct Pixel_compare: public binary_function<Pixel&, Pixel&, bool> {
// bool operator() (Pixel& a, Pixel& b) {
// return a.intens < b.intens;
// }
// };
// the queue redefined for pointers
typedef priority_queue<Pixel*, vector<Pixel*>, Pixel_compare> PixelPrQueue;
// was: typedef priority_queue<Pixel, vector<Pixel>, Pixel_compare>
PixelPrQueue;
SEXP
lib_filterInvWS (SEXP x) {
SEXP res;
int i, j, index;
double val;
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++;
for (int im = 0; im < nz; im++ ) {
double * src = &( REAL(x)[ im * nx * ny ] );
double * tgt = &( REAL(res)[ im * nx * ny ] );
PixelPrQueue pq;
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;
// new pixels are created as pointer to objects
// was: pq.push( Pixel(i, j, val) );
pq.push( new Pixel(i, j, val) );
continue;
}
tgt[ index ] = BG;
}
// printed and all pointers deleted
Pixel * px;
while ( !pq.empty() ) {
px = pq.top();
pq.pop();
Rprintf("%f\n", px->intens);
delete px;
}
}
UNPROTECT (nprotect);
return res;
}
The above works fine. The "Compare" operator is defined differently from
my previous post, but both fail if used with references.
Oleg
Duncan Murdoch wrote:
> 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;
>> }
>>
>>
>>
>>
--
Dr Oleg Sklyar * EBI/EMBL, Cambridge CB10 1SD, England * +44-1223-494466
More information about the R-help
mailing list