Tuesday 15 February 2011

Undefined behavior when passing C++ objects to C routine -



Undefined behavior when passing C++ objects to C routine -

update

i found if pass reference in constructor, prepare problem in a.cpp!

i.e. infopass(vector<double> &arg0, vector<double> &arg1...), what's reason?

update

basically want phone call c code c++.

as explained in c mannual, avoid using gloabal variables, "void *fdata" provided addtional information, if not any, it's pointed null.

int f(unsigned ndim, unsigned npts, const double *x, void *fdata, unsigned fdim, double *fval);

now need pack c++ objects , pass "f" through *fdata argument, way think of define class "infopass", , pass c routine.

my c++ snippet (example a.cpp , b.cpp, doesn't work while b ok):

// illustration a.cpp #include "cubature.h" // c library called cubature #include "extern_cpp_class.hpp" // class infopass { public: extern_cpp_class obj1; extern_cpp_class obj2; extern_cpp_class obj3; double arr[3]; infopass(vector<double>arg0, vector<double>arg1, vector<double>arg2, vector<double>arg3) : obj1{arg0, arg1}, obj2{arg0, arg2}, obj3{arg0, arg3} {} }; // declaration of int f() , cubature() below in c code int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval); int main() { /*** ***/ infopass cubpass{arg0, arg1, arg2, arg3}; // initialize cubature(2, f, &cubpass, 2, xmin, xmax, 1e5, 0, 1e-5, error_paired, output, &err); /*** process output ***/ } int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval) { infopass *fcubpass=static_cast<infopass*>(fdata); /*** things fcubpass.obj1, .obj2 ... ***/ }

now, can compile(gcc) , run illustration a, strangely, there undefinded behaviors, gives nan, gives crazy numbers...

however, if instead in next way (example b, utilize pointers class) utilize "new" in f, works fine! wondering why? since prefer illustration b in need alway "new" somthing...

// illustration b.cpp class infopass { public: extern_cpp_class *obj1=null; extern_cpp_class *obj2=null; extern_cpp_class *obj3=null; double arr[3]; ~infopass(){ delete obj1; delete obj2; delete obj3; } } int main() { /*** ***/ infopass cubpass; // declare cubpass.obj1 = new extern_cpp_class(arg0,arg1); cubpass.obj2 = new extern_cpp_class(arg0,arg2); cubpass.obj3 = new extern_cpp_class(arg0,arg3); cubature(2, f, &cubpass, 2, xmin, xmax, 1e5, 0, 1e-5, error_paired, output, &err); /*** process output ***/ } int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval) { infopass *fcubpass=static_cast<infopass*>(fdata); /*** things fcubpass->obj1, .obj2 ... ***/ }

just shot in dark here.

what extern_cpp_class objects initialization parameters? if take , store vector arguments references, you'd run problem original a.cpp since arguments temporary copies destroyed — invalidating references — after cubpass's constructor finished executing. switching passing references prepare ensuring extern_cpp_class objects receive references vectors created in main (presumably) remain valid until programme exits (or @ to the lowest degree until you're done working cubpass). in b.cpp, constructors references such vectors, hence no problems.

c++ c numeric

No comments:

Post a Comment