gpt4 book ai didi

c - 我做错了什么或者这是 Go 的 C 编译器中的错误?

转载 作者:IT王子 更新时间:2023-10-29 01:39:53 26 4
gpt4 key购买 nike

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

如果作为 cgo 函数调用,散列函数工作得很好,但是如果我尝试使用“ native ”版本,它会返回错误的散列。

我对 C 语言的了解足以让它正常工作,但在报告问题之前,我想确保我没有做错任何事情。

gist

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.
}

xxhash_9p.c:

#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 build && ./nocgo #9p native
134316512
981225178
$ go build && ./nocgo #cgo
981225178
981225178

长话短说:

当通过 Go 的 6c 使用时,C 函数返回错误值,当通过 CGO 调用时,相同的 C 函数返回正确值。

//编辑

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

来自mi...@golang.org:

the C compiler will eventually go away. Plan for that, so don't rely on it.

Note the Plan 9 C compiler isn't fully ANSI compliant, and we're not going to fix bugs in it (because we control both the compiler and its input, we will just workaround its bugs).

最佳答案

经过一些挖掘,改变了函数签名

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

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

并称它为:

var u uint32
XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0, &u)

返回正确的散列。

我仍然不确定发生了什么,它应该像原来那样工作,但我猜运行时在幕后做了一些魔术。

关于c - 我做错了什么或者这是 Go 的 C 编译器中的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25048775/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com