2015-08-10 4 views
1

Я звоню функцию C через ОЦП таким образом:Как разрешить изменение значения указателя в вызове функции? Это ошибка cgo?

var _outptr_7 C.double 
var _outptr_8 C.double 
var kk uintptr = uintptr(unsafe.Pointer(&_outptr_7)) 
gogsl.InitializeGslFunction(f) 
_result := int32(C.gsl_integration_qags((*C.gsl_function)(unsafe.Pointer(f.CPtr())), C.double(a), C.double(b), C.double(epsabs), C.double(epsrel), C.size_t(limit), (*C.gsl_integration_workspace)(unsafe.Pointer(workspace.Ptr())), (*C.double)(&_outptr_7), (*C.double)(&_outptr_8))) 
fmt.Printf("%10.10X\n",kk) 
return _result, *(*float64)(unsafe.Pointer(&_outptr_7)), *(*float64)(unsafe.Pointer(&_outptr_8)) 

Теперь kk здесь для целей отладки. Я изменил функцию C gsl_integration_qags для вывода 8-го аргумента он получает (это &_outptr_7, то _<n> отсчета от 0!)

(The InitializeGslFunction может быть проигнорирован для целей здесь ...)

Два значения - kk и выход функции C - точно соответствуют.

Тем не менее, я получаю номер, отличный от функции функции C - он устанавливает 8-й аргумент по косвенности. Я уверен, что это правильно, я наблюдал, как он работает в gdb.

Это выглядит следующим образом: (опуская линий, которые только для чтения (gdb), где я попал ввести повторить команду)

Breakpoint 3, qags (f=0xc20800a260, a=0, b=1, epsabs=0, epsrel=9.9999999999999995e-08, limit=1000, workspace=0x782ec0, result=0xc208031e28, abserr=0xc208031e20, q=0x7ffff79ad12c <gsl_integration_qk21>) 
at qags.c:479 
479 *result = res_ext; 
(gdb) n 
480 *abserr = err_ext; 
(gdb) p *result 
$1 = -4.0000000000000853 
(gdb) p result 
$2 = (double *) 0xc208031e28 
(gdb) n 
482 if (err_ext == GSL_DBL_MAX) 
485 if (error_type || error_type2) 
513  double max_area = GSL_MAX_DBL (fabs (res_ext), fabs (area)); 
515  if (!positive_integrand && max_area < 0.01 * resabs0) 
520  double ratio = res_ext/area; 
522  if (ratio < 0.01 || ratio > 100.0 || errsum > fabs (area)) 
526 goto return_error; 
535 if (error_type > 2) 
540 if (error_type == 0) 
542  return GSL_SUCCESS; 
573 } 
gsl_integration_qags (f=0xc20800a260, a=0, b=1, epsabs=0, epsrel=9.9999999999999995e-08, limit=1000, workspace=0x782ec0, result=0xc208031e28, abserr=0xc208031e20) at qags.c:53 
53 return status ; 
54 } 

// Правильное значение (-4,0) возвращается из функции C.

_cgo_3ce45c051e63_Cfunc_gsl_integration_qags (v=0xc208031db8) at /home/dtrombley/go/src/github.com/dtromb/gogsl/numint/numint.go:241 
asmcgocall() at /usr/lib/golang/src/runtime/asm_amd64.s:669 
669  MOVQ 48(SP), DI 
670  MOVQ (g_stack+stack_hi)(DI), SI 
671  SUBQ 40(SP), SI 
672  MOVQ DI, g(CX) 
673  MOVQ SI, SP 
asmcgocall() at /usr/lib/golang/src/runtime/asm_amd64.s:674 
674  RET 
runtime.asmcgocall_errno() at /usr/lib/golang/src/runtime/asm_amd64.s:627 
627  MOVL AX, ret+16(FP) 
runtime.asmcgocall_errno() at /usr/lib/golang/src/runtime/asm_amd64.s:628 
628  RET 
runtime.cgocall_errno (fn=0x405210 <_cgo_3ce45c051e63_Cfunc_gsl_integration_qags>, arg=0xc20805fdb8, ~r2=0) at /usr/lib/golang/src/runtime/cgocall.go:132 
132  exitsyscall() 
134  return errno 

// ОЦП C клей собирается вернуться из вызова в Go вызывающих

github.com/dtromb/gogsl/numint._Cfunc_gsl_integration_qags (p0=0xc20800a260, p1=0, p2=1, p3=0, p4=9.9999999999999995e-08, p5=1000, p6=0x782ec0, p7=0xc20805fe28, p8=0xc20805fe20, r1=0) 
at /home/dtrombley/go/src/github.com/dtromb/gogsl/numint/:92 
92 /home/dtrombley/go/src/github.com/dtromb/gogsl/numint/: No such file or directory. 

// Взрывы, она сломана. Значение p7 в возврате val struct равно/отличается от значения, которое было в/... . Местонахождение _outptr_7 изменилось.

(gdb) p p7 
$3 = (github.com/dtromb/gogsl/numint._Ctype_double *) 0xc20805fe28 
(gdb) p *p7 
$4 = 0 
(gdb) n 
github.com/dtromb/gogsl/numint.Qags (f=0xc20805ff58, a=0, b=1, epsabs=0, epsrel=9.9999999999999995e-08, limit=1000, workspace=0xc20800a1d0, ~r7=7753968, ~r8=0, ~r9=0) 
at /home/dtrombley/go/src/github.com/dtromb/gogsl/numint/numint.go:75 
75  fmt.Printf("%10.10X\n",kk) 
C208031E28 
76  return _result, *(*float64)(unsafe.Pointer(&_outptr_7)), *(*float64)(unsafe.Pointer(&_outptr_8)) 
(gdb) p _outptr_7 
$5 = 0 
(gdb) p &_outptr_7 
$6 = (float64 *) 0xc20805fe28 

// Но правильное значение все еще висит там.

(gdb) p $1 
$7 = -4.0000000000000853 

Итак, что дает? Что здесь происходит? Как исправить/обход?

Вот привязки ОЦП, показывающий отображение структуры, для полноты:

void 
_cgo_a9ebceabba03_Cfunc_gsl_integration_qags(void *v) 
{ 
    struct { 
      gsl_function* p0; 
      double p1; 
      double p2; 
      double p3; 
      double p4; 
      size_t p5; 
      gsl_integration_workspace* p6; 
      double* p7; 
      double* p8; 
      int r; 
      char __pad76[4]; 
    } __attribute__((__packed__, __gcc_struct__)) *a = v; 
    char *stktop = _cgo_topofstack(); 
    __typeof__(a->r) r = gsl_integration_qags((void*)a->p0, a->p1, a->p2, a->p3, a->p4, a->p5, (void*)a->p6, (void*)a->p7, (void*)a->p8); 
    a = (void*)((char*)a + (_cgo_topofstack() - stktop)); 
    a->r = r; 
} 

Исправлена ​​ошибка происходит или не происходит случайным образом в зависимости от некоторых деталей компиляции, которые не должны влиять на семантику - добавление линии, которая печатает out & _outptr_7 перед вызовом функции C заставляет его возвращать правильно, например. Внесение других изменений в код вернет его обратно и т. Д.

Что-то я делаю неправильно? Или ошибка в cgo?

+0

Вы проверили go1.5 гс, чтобы увидеть, если он ведет себя по-другому? Можете ли вы предоставить полный, управляемый пример? Я не вижу ничего более очевидного, но это скорее вопрос для списка рассылки, если вы хотите получить какую-либо помощь по отладке (хотя с предстоящим выпуском все может быть немного медленнее). – JimB

+0

Пробовал список рассылки, без ответа (мой msg даже не писал, может быть, модны заняты или что-то еще).Мне не нужна помощь для отладки - я хочу знать, изменился ли адрес этого значения (простой «var x » в стеке Go), что является законным/предполагаемым поведением или нет. Вопрос в том, «это ошибка»? – BadZen

+0

Не пробовал разработку/кровоточащий край Go. Если бы я мог сделать минимальный тестовый пример, я бы использовал его здесь - поскольку я сказал, что это происходит случайно, на некоторых сборках да и на некоторых сборках нет - и включает популярную (большую) библиотеку C .... – BadZen

ответ