Я боролся с проблемой в течение нескольких часов, и я в своем уме.
По сути, у меня есть функции, которые принимают несколько переменных и выводят другие. Вы знаете, довольно стандартные вещи.
Проблема в том, что одна из моих переменных не изменяется, но становится перепутанной. Я могу только предположить, что где-то происходит перелив памяти в ее пространство, но не могу понять, где, почему и как.
Ниже приведен очень упрощенный код (полная версия составляет около 300 строк и должна вычислять точки и производные сплайновой поверхности «NURBS»). Приносим извинения за количество неиспользуемых входных данных в функциях (я отключил и удалил большую часть кода, чтобы помочь вам, ребята, понять, что не так).
Когда он скомпилирован и запущен, вывод на экран:
Start Mex 40, 30
Outer Function Part 1 40, 30
Inner Function Part 1 40, 30
Inner Function Part 2 40, 30
Outer Function Part 2 817645044, 1069852220
Outer Function Part 3 817645044, 1069852220
End Mex 817645044, 1069852220
Однако вывод, очевидно, должен быть последовательным (40, 30).
Так что я был бы чрезвычайно признателен, если бы кто-нибудь мог предупредить меня о причине, по которой я идиот, чтобы я мог не быть идиотом в будущем.
void Simple_Separate_Parametrics(double* t_frac, double* t_crd_dbl, double t_full) {
*t_crd_dbl = floor((double)t_full);
*t_frac = t_full - *t_crd_dbl;
}
void Calc_Point_and_XJacobian_On_SplurfaceMap(double* P, double* J, bool* Valid, unsigned long* RelCrds, double* s, double* t, double* M, double* X, unsigned long* Crds, unsigned long* GridSize) {
double *t_frac;
double *t_crd;
mexPrintf("Inner Function Part 1 %u, %u\n", *(GridSize), *(GridSize+1));
Simple_Separate_Parametrics(t_frac, t_crd, *t);
mexPrintf("Inner Function Part 2 %u, %u\n", *(GridSize), *(GridSize+1));
}
void Points_and_XJacobian_on_Splurface(double* Points, double* Jacobian, bool* Valid, double* s, double* t, double* M, double* X, unsigned long* GridSize, size_t NumPts) {
double* J = (double*)malloc(16*sizeof(double));
unsigned long n, Xlen, Vpts;//m,
Vpts = *(GridSize+1) + 3;
Xlen = (*(GridSize) + 3)*Vpts;
unsigned long* Crds = (unsigned long*)malloc(Xlen*sizeof(unsigned long));
unsigned long* RelCrds = (unsigned long*)malloc(16*sizeof(unsigned long));
mexPrintf("Outer Function Part 1 %u, %u\n", *(GridSize), *(GridSize+1));
for (n = 0; n < 1; ++n) {//NumPts
Calc_Point_and_XJacobian_On_SplurfaceMap(Points + n, J, Valid + n, RelCrds, s + n, t + n, M, X, Crds, GridSize);
mexPrintf("Outer Function Part 2 %u, %u\n", *(GridSize), *(GridSize+1));
}
mexPrintf("Outer Function Part 3 %u, %u\n", *(GridSize), *(GridSize+1));
free(J); free(Crds); free(RelCrds);
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
// [Points, Jacobian, Valid] = Function( s, t, X, GridSize)
double *Points, *Jacobian, *s, *t, *X, *M;
size_t NumPts, Xlen;
unsigned long* GridSize;
bool* Valid;
s = mxGetPr(prhs[0]);
t = mxGetPr(prhs[1]);
X = mxGetPr(prhs[2]);
GridSize = (unsigned long*)malloc(2*sizeof(unsigned long));
*(GridSize ) = 40;
*(GridSize+1) = 30;
mexPrintf("Start Mex %u, %u\n", *GridSize, *(GridSize+1));
NumPts = mxGetN(prhs[0]);
Xlen = mxGetM(prhs[2])*mxGetN(prhs[2]);
M = (double*)malloc(16*sizeof(double));
if (nlhs == 3) {
plhs[0] = mxCreateDoubleMatrix( 1, NumPts, mxREAL);
Points = mxGetPr(plhs[0]);
plhs[1] = mxCreateDoubleMatrix( NumPts, Xlen, mxREAL);
Jacobian = mxGetPr(plhs[1]);
plhs[2] = mxCreateLogicalMatrix( NumPts, 1);
Valid = (bool*)mxGetData(plhs[2]);
Points_and_XJacobian_on_Splurface(Points, Jacobian, Valid, s, t, M, X, GridSize, NumPts);
}
mexPrintf("End Mex %u, %u\n", *(GridSize), *(GridSize+1));
free(M); free(GridSize);
}
Xlen = (*(GridSize) + 3)*Vpts;
, станет легче. По-видимому, нынешняя указательность для вас слишком велика, и у вас нет причин избегать более C++-подобных вещей, так что... и попробуйте valgrind. - person deviantfan   schedule 10.09.2015main
,mexFunction
— это точка входа. По сути, это so/dll, который вызывает MATLAB. При этом я согласен с вашей оценкой, что ОП должен перестать быть таким счастливым указателем и попытаться упростить вещи. DavidGW, вы можете запускать mex-функции под отладчиком, вы можете попробовать. - person Praetorian   schedule 10.09.2015mexFunction
является эквивалентом MATLAB дляmain()
- person Mad Physicist   schedule 10.09.2015std::pair
илиboost::tuple
или простую структуру изSimple_Separate_Parametrics
вместо того, чтобы передавать выходные данные через указатели? Почему вы так много передаете через указатели, а не ссылки? А как насчет const-корректности? Почему у вас есть функции, которые принимают миллиарды параметров вместо структуры (или кортежа)? Почему нет RAII? Почему выmalloc
представляете простой массив из 16 двойников (J)? Это читается как C, а не C++. Не пишите C, когда у вас есть компилятор C++. Не используйте голые указатели на собственные данные, используйтеstd::unique_ptr
, но предпочитайте значения в стеке для небольших фиксированных массивов. Ургх! - person Kuba hasn't forgotten Monica   schedule 10.09.2015Also, most of the pointers that are used are for large vectors of variable length, so they can't really be removed.
и т.д. и т.п.: Это неправильно. Как сказал КубаОбер, здесь вам не нужны необработанные указатели и malloc. - person deviantfan   schedule 10.09.2015