如何解决函数调用中指针值的变化?这是cgo错误吗?

如何解决函数调用中指针值的变化?这是cgo错误吗?,c,go,cgo,C,Go,Cgo,我正在通过cgo调用一个C函数,因此: 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

我正在通过cgo调用一个C函数,因此:

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\u integration\u qags
,以输出它接收到的第8个参数(即
从0开始计数!)

(此处可忽略初始化GSL功能的

两个值-
kk
和C函数输出-完全匹配

但是,我得到的数字与C函数返回的数字不同——它通过间接方式设置第8个参数。我确信这是正确的,我看过它在gdb中工作

它看起来是这样的:(省略了刚刚读取
(gdb)
的行,我点击enter来重复命令)

//砰,它坏了。return val struct中的p7值与/中的值不同输出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
那么,有什么好处呢?这是怎么回事?如何修复/解决

为了完整起见,以下是显示结构映射的cgo绑定:

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;
}
错误的发生与否取决于编译的某些细节,这些细节不应影响语义——例如,在调用C函数之前添加一行打印出&_outptr_7会导致它正确返回。对代码进行其他更改会将其还原,等等


我做错什么了?还是cgo中的错误?

这是由于Go 1.4中的错误造成的。固定在1.5


这是由于Go 1.4中的错误造成的。固定在1.5


您是否测试过go1.5 rc,以查看其性能是否有任何不同?你能提供一个完整的、可运行的例子吗?我看不到其他明显的问题,但如果您需要一些调试帮助(尽管即将发布的版本可能会有点慢),这更像是邮件列表的问题。尝试了邮件列表,没有回应(我的msg甚至没有发布-可能mods很忙或其他)。我不需要调试帮助—我想知道所演示的值更改地址(一个简单的“var x”在Go堆栈上)是否合法/预期行为。问题是“这是一个bug吗”?还没有尝试过开发/前沿Go。如果我能做一个最小的测试用例,我会在这里使用它——正如我所说,这件事是随机发生的,在一些版本上是,在一些版本上不是——并且涉及一个流行的(大型)C库……正如我所建议的,你试过go1.5了吗?它可能与逃逸分析有关,并且有适当的修复。Go指针需要在cgo调用的整个生命周期内处于活动状态,但对于go1.4中标记为非转义的堆栈分配值,这种情况并不总是发生。可能是因为您测试了go1.5 rc以查看其行为是否有所不同?你能提供一个完整的、可运行的例子吗?我看不到其他明显的问题,但如果您需要一些调试帮助(尽管即将发布的版本可能会有点慢),这更像是邮件列表的问题。尝试了邮件列表,没有回应(我的msg甚至没有发布-可能mods很忙或其他)。我不需要调试帮助—我想知道所演示的值更改地址(一个简单的“var x”在Go堆栈上)是否合法/预期行为。问题是“这是一个bug吗”?还没有尝试过开发/前沿Go。如果我能做一个最小的测试用例,我会在这里使用它——正如我所说,这件事是随机发生的,在一些版本上是,在一些版本上不是——并且涉及一个流行的(大型)C库……正如我所建议的,你试过go1.5了吗?它可能与逃逸分析有关,并且有适当的修复。Go指针需要在cgo调用的整个生命周期内处于活动状态,但对于go1.4中标记为非转义的堆栈分配值,这种情况并不总是发生
(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;
}