I am developing an R package with C++ functions. I use Rcpp. Everything was fine when writing and testing. However, when I finished and ran it in a loop, I occasionally got the following warnings and errors:
Warning: stack imbalance in '.Call', 78 then 77
Warning: stack imbalance in '{', 75 then 74
Warning: stack imbalance in '.Call', 78 then 79
Warning: stack imbalance in '{', 75 then 76
Warning: stack imbalance in '.Call', 78 then 77
Warning: stack imbalance in '{', 75 then 74
So I googled stack imbalance and I found:
This article states stack imbalance is usually caused by differences (mismatching) in calling convention among languages. As far as I know, callng convention is an agreement on whether the caller function to delete local variables or the callee functions to delete.
And I found this:
http://www.stats.uwo.ca/faculty/murdoch/software/compilingDLLs/
It says R is using cdecl
while C++ uses stdcall
.
"If your function uses
stdcall
instead ofcdecl
, there will likely be a crash when you return, because your parameters will be removed from the stack after they're already gone."
Please let me know if I made any mistakes in the statement.
This is the C++ function being called by my R code:
//[[Rcpp::export]]
int compute(SEXP p_in, Rcpp::NumericVector a) {
Rcpp::XPtr<emcdf> p(p_in);
p->cdf(a);
return p->getResult();
}
//p_in is an external pointer(pointer to an emcdf object in C++)
So, my question is, how do I fix this?
I appreciate your help.
More details and code 2.14.2017
Thank you guys for answering. Here's more code:
//declaration of class "emcdf"
class emcdf{
public:
explicit emcdf(Rcpp::NumericMatrix& x, int n);
~emcdf();
void cdf(Rcpp::NumericVector& a);
int getResult();
private:
int num;
int k;
std::thread* t;
std::vector<Rcpp::NumericMatrix*> data;
int size;
int* result;
void (*ptr) (Rcpp::NumericMatrix*, Rcpp::NumericVector, int*);
void find_func();
};
//definition of class "emcdf"
emcdf::emcdf(Rcpp::NumericMatrix& x, int n){
//initialize members
t = new std::thread[n];
num = n;
k = x.ncol();
size = x.nrow()/num;
result = new int[num];
find_func();
int i = 0;
for(; i<num - 1; ++i)
data.push_back(copy(x, i*size, size));
data.push_back(copy(x, i*size, x.nrow() - i*size));
}
emcdf::~emcdf(){
delete[] t;
for(int i=0; i<num; ++i)
delete data[i];
delete[] result;
}
void emcdf::cdf(Rcpp::NumericVector& a){
for(int i=0; i<num; ++i){
t[i] = std::thread(*ptr, data[i], a, result + i);
}
for(int i=0; i<num; ++i)
t[i].join();
}
int emcdf::getResult(){
int sum = 0;
for(int i=0; i<num; ++i)
sum += result[i];
return sum;
}
//other functions
Rcpp::NumericMatrix* copy(Rcpp::NumericMatrix& x, int row, int nrow){
NumericMatrix* out = new NumericMatrix(nrow, x.ncol());
int firstRow = 0;
while(firstRow < nrow){
for(int j=0; j<x.ncol(); ++j){
out->at(firstRow,j) = x.at(firstRow + row,j);
}
++firstRow;
}
return out;
}
//makes "emcdf" pointer
//[[Rcpp::export]]
RcppExport SEXP build(SEXP x_in, int num){
Rcpp::NumericMatrix x(x_in);
emcdf* em = new emcdf(x, num);
Rcpp::XPtr<emcdf> p(em, true);
return p;
}
//take pointer of "emcdf" from build() and compute cdf results
//[[Rcpp::export]]
int compute(SEXP& p_in, Rcpp::NumericVector& a){
Rcpp::XPtr<emcdf> p(p_in);
p->cdf(a);
return p->getResult();
}
The parameter SEXP& p_in in compute() is passed from the return of build(). In my R code, I called compute() and got the stack imbalance error. It doesn't appear every time, but when called over 1000 times continuously, it's likely to go wrong.
Kevin Ushey suggested:
"It looks like the issue here is simply that you're attempting to use R / Rcpp within a separate thread, and that unfortunately won't work (as you can end up triggering the garbage collector from a separate thread)."
Does that mean if I avoid using Rcpp functions/ objects in separate threads, for example, don't use NumericMatrix in *ptr
which my threads run, this error will be fixed?
Thank you.