Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我是做错了什么,还是这是Go'中的一个bug;编译程序?_C_Go_Cgo - Fatal编程技术网

C 我是做错了什么,还是这是Go'中的一个bug;编译程序?

C 我是做错了什么,还是这是Go'中的一个bug;编译程序?,c,go,cgo,C,Go,Cgo,所以我从使用cgo移植到Go的原生9PC,但是我遇到了一个相当奇怪的问题 如果将哈希函数作为cgo函数调用,则该函数可以很好地工作,但是如果我尝试使用“本机”版本,它将返回错误的哈希 我知道足够的C语言使它工作,但在报告问题之前,我想确保我没有做错任何事情 xxhash.go: //#include "xxhash_9p.c" //import "C" //uncomment this and comment the next line for the cgo version func XXH

所以我从使用cgo移植到Go的原生9PC,但是我遇到了一个相当奇怪的问题

如果将哈希函数作为cgo函数调用,则该函数可以很好地工作,但是如果我尝试使用“本机”版本,它将返回错误的哈希

我知道足够的C语言使它工作,但在报告问题之前,我想确保我没有做错任何事情

xxhash.go

//#include "xxhash_9p.c"
//import "C" //uncomment this and comment the next line for the cgo version
func XXH32_test(in unsafe.Pointer, l uint32, seed uint32) uint32


func GoXXH32(in []byte, seed uint32) (h uint32) {
    //omitted, full version in the gist above
}

func main() {
    b := []byte("ABCDEFGLAALSDLSD:LSDL:DL:DL:SDL:SL:DSL:DL:DSL:DL:{W{EOQWExzghp[[")
    fmt.Println(XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0)) //uncomment this and comment the next line for the cgo version
    //fmt.Println(C.XXH32_test(unsafe.Pointer(&b[0]), C.uint(len(b)), 0))
    fmt.Println(GoXXH32(b, 0)) //this is tested against the C implementation and it's the right hash.
}
#define PRIME32_1   2654435761U
#define PRIME32_2   2246822519U
#define PRIME32_3   3266489917U
#define PRIME32_4    668265263U
#define PRIME32_5    374761393U

#define U32 unsigned int
typedef struct _U32_S { U32 v; } U32_S;
#define A32(x) (((U32_S *)(x))->v)

U32 ·XXH32_test(const void* input, U32 len, U32 seed) {
//static U32 XXH32_test(const void* input, U32 len, U32 seed) {
    const char* p = (const char*)input;
    const char* bEnd = p + len;
    U32 h32;

    #define XXH_get32bits(p) A32(p)
    #define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))

    if (len>=16) {
        const char* const limit = bEnd - 16;
        U32 v1 = seed + PRIME32_1 + PRIME32_2;
        U32 v2 = seed + PRIME32_2;
        U32 v3 = seed + 0;
        U32 v4 = seed - PRIME32_1;
        do
        {
            v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
            v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
            v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
            v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
        } while (p<=limit);

        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
    }
    else
    {
        h32  = seed + PRIME32_5;
    }

    h32 += (unsigned long) len;
    while (p<=bEnd-4) {
        h32 += XXH_get32bits(p) * PRIME32_3;
        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
        p+=4;
    }

    while (p<bEnd) {
        h32 += (*p) * PRIME32_5;
        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
        p++;
    }

    h32 ^= h32 >> 15;
    h32 *= PRIME32_2;
    h32 ^= h32 >> 13;
    h32 *= PRIME32_3;
    h32 ^= h32 >> 16;
    return h32;
}
xxhash_9p.c

//#include "xxhash_9p.c"
//import "C" //uncomment this and comment the next line for the cgo version
func XXH32_test(in unsafe.Pointer, l uint32, seed uint32) uint32


func GoXXH32(in []byte, seed uint32) (h uint32) {
    //omitted, full version in the gist above
}

func main() {
    b := []byte("ABCDEFGLAALSDLSD:LSDL:DL:DL:SDL:SL:DSL:DL:DSL:DL:{W{EOQWExzghp[[")
    fmt.Println(XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0)) //uncomment this and comment the next line for the cgo version
    //fmt.Println(C.XXH32_test(unsafe.Pointer(&b[0]), C.uint(len(b)), 0))
    fmt.Println(GoXXH32(b, 0)) //this is tested against the C implementation and it's the right hash.
}
#define PRIME32_1   2654435761U
#define PRIME32_2   2246822519U
#define PRIME32_3   3266489917U
#define PRIME32_4    668265263U
#define PRIME32_5    374761393U

#define U32 unsigned int
typedef struct _U32_S { U32 v; } U32_S;
#define A32(x) (((U32_S *)(x))->v)

U32 ·XXH32_test(const void* input, U32 len, U32 seed) {
//static U32 XXH32_test(const void* input, U32 len, U32 seed) {
    const char* p = (const char*)input;
    const char* bEnd = p + len;
    U32 h32;

    #define XXH_get32bits(p) A32(p)
    #define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))

    if (len>=16) {
        const char* const limit = bEnd - 16;
        U32 v1 = seed + PRIME32_1 + PRIME32_2;
        U32 v2 = seed + PRIME32_2;
        U32 v3 = seed + 0;
        U32 v4 = seed - PRIME32_1;
        do
        {
            v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
            v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
            v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
            v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
        } while (p<=limit);

        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
    }
    else
    {
        h32  = seed + PRIME32_5;
    }

    h32 += (unsigned long) len;
    while (p<=bEnd-4) {
        h32 += XXH_get32bits(p) * PRIME32_3;
        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
        p+=4;
    }

    while (p<bEnd) {
        h32 += (*p) * PRIME32_5;
        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
        p++;
    }

    h32 ^= h32 >> 15;
    h32 *= PRIME32_2;
    h32 ^= h32 >> 13;
    h32 *= PRIME32_3;
    h32 ^= h32 >> 16;
    return h32;
}
TL;医生:

//#include "xxhash_9p.c"
//import "C" //uncomment this and comment the next line for the cgo version
func XXH32_test(in unsafe.Pointer, l uint32, seed uint32) uint32


func GoXXH32(in []byte, seed uint32) (h uint32) {
    //omitted, full version in the gist above
}

func main() {
    b := []byte("ABCDEFGLAALSDLSD:LSDL:DL:DL:SDL:SL:DSL:DL:DSL:DL:{W{EOQWExzghp[[")
    fmt.Println(XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0)) //uncomment this and comment the next line for the cgo version
    //fmt.Println(C.XXH32_test(unsafe.Pointer(&b[0]), C.uint(len(b)), 0))
    fmt.Println(GoXXH32(b, 0)) //this is tested against the C implementation and it's the right hash.
}
#define PRIME32_1   2654435761U
#define PRIME32_2   2246822519U
#define PRIME32_3   3266489917U
#define PRIME32_4    668265263U
#define PRIME32_5    374761393U

#define U32 unsigned int
typedef struct _U32_S { U32 v; } U32_S;
#define A32(x) (((U32_S *)(x))->v)

U32 ·XXH32_test(const void* input, U32 len, U32 seed) {
//static U32 XXH32_test(const void* input, U32 len, U32 seed) {
    const char* p = (const char*)input;
    const char* bEnd = p + len;
    U32 h32;

    #define XXH_get32bits(p) A32(p)
    #define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))

    if (len>=16) {
        const char* const limit = bEnd - 16;
        U32 v1 = seed + PRIME32_1 + PRIME32_2;
        U32 v2 = seed + PRIME32_2;
        U32 v3 = seed + 0;
        U32 v4 = seed - PRIME32_1;
        do
        {
            v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
            v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
            v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
            v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
        } while (p<=limit);

        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
    }
    else
    {
        h32  = seed + PRIME32_5;
    }

    h32 += (unsigned long) len;
    while (p<=bEnd-4) {
        h32 += XXH_get32bits(p) * PRIME32_3;
        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
        p+=4;
    }

    while (p<bEnd) {
        h32 += (*p) * PRIME32_5;
        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
        p++;
    }

    h32 ^= h32 >> 15;
    h32 *= PRIME32_2;
    h32 ^= h32 >> 13;
    h32 *= PRIME32_3;
    h32 ^= h32 >> 16;
    return h32;
}
当通过Go的6c使用时,C函数返回错误的值,当通过CGO调用时,相同的精确C函数返回正确的值

//编辑

我在上得到了回应,它不会得到修复,9p工具链最终会消失

米…@golang.org

C编译器最终将消失。为此做好计划,所以不要依赖 在上面

注意Plan9C编译器不是完全符合ANSI标准的,我们也不是 将修复其中的bug(因为我们同时控制编译器及其 输入时,我们只需解决它的bug)


经过一些挖掘,将函数签名从

U32 ·XXH32_test(const void* input, U32 len, U32 seed)

并称之为:

var u uint32
XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0, &u)
返回正确的哈希值


我仍然不确定到底发生了什么,它应该按照最初的方式工作,但我猜运行时在幕后发挥了一些神奇的作用。

您确实知道plan9编译器正在从Go中删除,对吗?我的意思是,这可能很有趣,但我不会花太多精力将某些东西移植到9p上。@Keith correct,我更改了它。JimB我甚至不确定他们是否会完全删除它,目前还没有官方立场,我知道它至少不会在1.4中删除。我能找到的唯一文件是,我不知道9p是否会在1.4版中消失,但我认为可能会在1.5版之前消失。我知道Russ说他们计划从源代码中删除所有非gcc C,一旦完成,plan9编译器将被删除。不知何故,这个问题似乎不完整。不确定什么是不完整的,问题很清楚,为什么函数通过6c调用时返回错误的散列,但通过cgo返回正确的散列?是的,是的。互联网上有一份文件描述了这一点,但我不知道它在哪里。请不要在自己的代码中使用Plan9C编译器。与cgo相比,速度提高了近50%,哦,太可惜了。@OneOfOne:尝试将它们与更大的输入进行比较。plan9编译器没有得到很好的优化,当go-cgo转换不是一个很重要的因素时,cgo可能会胜出。我在一个使用
map[uint64 hash]*s
的项目中使用了它,因此输入通常在30-100字节左右。