Преобразование типа из байтового фрагмента в структуру с небезопасным

Я пытаюсь понять, почему мой код на Go не работает так, как я думал. Когда я выполняю этот тест, он терпит неудачу:

func TestConversion(t *testing.T) {
    type myType struct {
        a     uint8
        value uint64
    }
    myVar1 := myType{a: 1, value: 12345}

    var copyFrom []byte
    copyFromHeader := (*reflect.SliceHeader)(unsafe.Pointer(&copyFrom))
    copyFromHeader.Data = uintptr(unsafe.Pointer(&myVar1))
    copyFromHeader.Cap = 9
    copyFromHeader.Len = 9

    copyTo := make([]byte, len(copyFrom))

    for i := range copyFrom {
        copyTo[i] = copyFrom[i]
    }

    myVar2 := (*myType)(unsafe.Pointer(&copyFrom[0]))
    myVar3 := (*myType)(unsafe.Pointer(&copyTo[0]))

    if myVar2.value != myVar3.value {
        t.Fatalf("Expected myVar3.value to be %d, but it is %d", myVar2.value, myVar3.value)
    }
}

Результатом будет:

slab_test.go:67: Expected myVar3.value to be 12345, but it is 57

Однако, если я увеличиваю copyFromHeader.Data на 1 перед копированием данных, тогда все работает нормально. Нравится:

copyFromHeader.Data = uintptr(unsafe.Pointer(&myVar1)) + 1

Я не понимаю, почему кажется, что базовые данные сдвигаются на один байт.

Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
0
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Между a и value есть 7 байтов заполнения. Вы получаете только младший байт из 12345 (57) в value. Когда вы перемещаете copyFrom на один байт вниз, значения myVar2.value и myVar3.value равны 48 (второй байт из 12345), поэтому ваш тест проходит. Он должен работать, если вы измените 9 на 16.

Есть ли какая-то конкретная причина, по которой вы копируете структуру таким образом?

Большое вам спасибо, вы правы! Мы пытаемся поместить простую структуру с uint и uint8 в байтовый фрагмент, который мы получили от syscall.Mmap. Но когда мы попытались вернуть этот байтовый фрагмент обратно в структуру, должно быть, мы столкнулись с этой проблемой.

replay 06.01.2019 01:30

Другие вопросы по теме