Неверный адрес памяти или разыменование нулевого указателя в c-shared режиме сборки Голанга - PullRequest
0 голосов
/ 22 ноября 2018

Я создал приложение Node, которое вызывает код golang для дорогостоящей операции.Я использую библиотеку с именем gosync и использую опцию -buildmode = c-shared, которая приводит к двум файлам: .h file и .so file.

Вот источник, который я написална Голанге:

package main

import "C"

import (
    "errors"
    "os"
    "personal.io/go-wrapper/util"
)

func main() {}

//export Diff
func Diff(localFilePath string, summaryFilePath string) {
    util.Diff(localFilePath, summaryFilePath)
}

Функция util.Diff практически совпадает с примером, предоставленным здесь создателем gosync https://github.com/Redundancy/gosync-cmd/blob/master/src/gosync/diff.go. Только незначительное изменение параметра функции:

Iсобрал его с помощью этой команды:

go build -buildmode=c-shared -o gowrapper.so main.go

На случай, если вам интересно, что выводится в заголовке:

/* Created by "go tool cgo" - DO NOT EDIT. */

/* package command-line-arguments */


#line 1 "cgo-builtin-prolog"

#include <stddef.h> /* for ptrdiff_t below */

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

typedef struct { const char *p; ptrdiff_t n; } _GoString_;

#endif

/* Start of preamble from import "C" comments.  */
/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

typedef _GoString_ GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif

extern void Diff(GoString p0, GoString p1);

#ifdef __cplusplus
}
#endif

И тогда я вызвал функцию в своем приложении Node:

var ref = require("ref")
var ffi = require("ffi-napi")
var Struct = require("ref-struct")
var ArrayType = require("ref-array")
var LongArray = ArrayType(ref.types.longlong);

var GoSlice = Struct({
  data: LongArray,
  len: "longlong",
  cap: "longlong"
});
var GoString = Struct({
  p: "string",
  n: "longlong"
});

var gozsync = ffi.Library("./gowrapper.so", {
    Diff: ["void", [GoString, GoString]]
});

const originPath = "/home/ivan/Documents/testingground/crossfire/dummy.v1.txt"
let originGoString = new GoString();
originGoString["p"] = originPath;
originGoString["n"] = originPath.length;

const summaryPath = "/home/ivan/Documents/testingground/crossfire/dummy.v2.gosync"
let summaryGoString = new GoString();
summaryGoString["p"] = summaryPath;
summaryGoString["n"] = summaryPath.length;

console.log(gozsync.Diff(originGoString, summaryGoString));

Выполнение этого кода (js one) приведет к достижению главной цели (вычислению различий).Однако я не могу завершить это успешно:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x17 pc=0x7fa1e56fe842]

goroutine 17 [running, locked to thread]:
main._cgoexpwrap_dc7530d6a4e5_Diff.func1(0xc420245ea8)
        _cgo_gotypes.go:59 +0x42
main._cgoexpwrap_dc7530d6a4e5_Diff(0x2d775c0, 0x3d, 0x2d67860, 0x40, 0x0, 0x0)
        _cgo_gotypes.go:61 +0x92
Aborted (core dumped)

Моя гипотеза состоит в том, что память, которая содержит значение, необходимое для отложенной операции (например, экземпляр file при ее закрытии), каким-то образом была удалена механизмом сборщика мусора.(что похоже также перенесено в .so файл).Однако я не уверен, так как не могу найти ссылку на это утверждение.

Есть идеи относительно этой проблемы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...