Memory problem in conversion between Golang`s string and C Char* into For Range, exit status 3221226356

Viewed 249

Updated: I work on a Golang code that implements a C library through GCO. Between the arguments of the C function there is a *Cchar object. I convert the string to *char with the C.CString () function, but I have problems when I need to implement it with a for loop. Thanks to @peterSON I can move forward. Now, the program runs a little longer until it fails. Now I get results until the third cycle (of five). When starting the fourth, again it indicates "exit status 3221226356"

This is a piece of code:

package main

//#include <stdio.h>
//#include <stdlib.h>
//#cgo CFLAGS: -I C:/Go-Project/src/Astrocal
//#cgo LDFLAGS: -L C:/Go-Project/src/Astrocal72 -lswedll64
//#include "swephexp.h"
import "C"

import (
    "fmt"
    "unsafe"
)

...

func (P DATA) FixStarUT() {

    C.swe_set_ephe_path(C.CString("C:/sweph/ephe")) // connect to library C. 
    var Cxx [6]C.double
    var serr string
    var Cserr *C.char = C.CString(serr)
    var FixStarCchar *C.char = C.CString("")

    var iFLAG = []uint32{33026, 35074, 266, 2314, 98562, 100610, 65802, 67851} // 33026, 35074, 266, 2314, 98562, 100610, 65802, 67851
    var fixStarSlice = []string{"aboras", "achernar", "adara", "ain", "vega"}

    fmt.Println("Memory Address of FixStarCchar before For Range ->", FixStarCchar)

    // For Range 1
    for i, valFixStar := range fixStarSlice {

        defer C.free(unsafe.Pointer(FixStarCchar))
        defer C.free(unsafe.Pointer(Cserr))

        FixStarCchar = C.CString(valFixStar)

        fmt.Println("\nExternal cycle:", i, "Star (valFixStar):", valFixStar)
        fmt.Println("Memory Add. of FixStarCchar ->", FixStarCchar)

        // For Range 2
        for i2, valSistem := range iFLAG {
            // C functions
            C.swe_set_topo(C.double(P.LONsite), C.double(P.LATsite), C.double(P.ALTsite))
            C.swe_fixstar_ut(FixStarCchar, C.double(P.JulianDay), C.int(valSistem), &Cxx[0], Cserr)

            // Exporting results to a slice
            var positionFixStar []float64
            positionFixStar = append(positionFixStar, float64(Cxx[0]), float64(Cxx[1]), float64(Cxx[2]), float64(Cxx[3]), float64(Cxx[4]), float64(Cxx[5]))

            fmt.Println("\tInternal cycle:", i2, "\tSistem:", valSistem, "\tPosition:", positionFixStar)
        }

    }
    C.swe_close() // disconnect library C
}

Output:

PS C:\Go-Project\src\Astrocal72> go run main.go
Memory Address of FixStarCchar before For Range -> 0x1019c80

External cycle: 0 Star (valFixStar): aboras
Memory Add. of FixStarCchar -> 0x1019ca0
        Internal cycle: 0       Sistem: 33026   Position: [331.7560238873596 -23.63731225621964 1 0 0 0]
        Internal cycle: 1       Sistem: 35074   Position: [343.5555314743071 -32.70632643606941 1 0 0 0]
        Internal cycle: 2       Sistem: 266     Position: [331.7521303243937 -23.639006118391627 1 0 0 0]
        Internal cycle: 3       Sistem: 2314    Position: [343.5525162650043 -32.709352136426915 1 0 0 0]
        Internal cycle: 4       Sistem: 98562   Position: [307.45659891000344 -23.63731225621964 1 0 0 0]
        Internal cycle: 5       Sistem: 100610  Position: [319.25465207507114 -32.705260202398776 1 0 0 0]
        Internal cycle: 6       Sistem: 65802   Position: [307.4527053470375 -23.63900611839163 1 0 0 0]
        Internal cycle: 7       Sistem: 67851   Position: [319.2516367429912 -32.7082857906988 0.9999999999999999 0 0 0]

External cycle: 1 Star (valFixStar): achernar
Memory Add. of FixStarCchar -> 0x101b3a0
        Internal cycle: 0       Sistem: 33026   Position: [344.86781077811537 -59.37245156484419 1 0 0 0]
        Internal cycle: 1       Sistem: 35074   Position: [24.13636287205359 -57.39092532881141 0.9999999999999999 0 0 0]
        Internal cycle: 2       Sistem: 266     Position: [344.86287075464315 -59.37668655703472 1 0 0 0]
        Internal cycle: 3       Sistem: 2314    Position: [24.138688732702057 -57.39568950801329 1 0 0 0]
        Internal cycle: 4       Sistem: 98562   Position: [320.56838580075924 -59.37245156484419 0.9999999999999998 0 0 0]
        Internal cycle: 5       Sistem: 100610  Position: [359.83323867384445 -57.39150066286222 1 0 0 0]
        Internal cycle: 6       Sistem: 65802   Position: [320.563445777287 -59.37668655703472 0.9999999999999999 0 0 0]
        Internal cycle: 7       Sistem: 67851   Position: [359.835563909282 -57.39626493585631 1 0 0 0]

External cycle: 2 Star (valFixStar): adara
Memory Add. of FixStarCchar -> 0x101ae40
        Internal cycle: 0       Sistem: 33026   Position: [110.31533627711894 -51.36455324165249 1 0 0 0]
        Internal cycle: 1       Sistem: 35074   Position: [104.3395190395512 -28.925572447433648 1 0 0 0]
        Internal cycle: 2       Sistem: 266     Position: [110.32409258962711 -51.363920733883326 0.9999999999999999 0 0 0]
        Internal cycle: 3       Sistem: 2314    Position: [104.34580120684954 -28.92581091916995 0.9999999999999999 0 0 0]
        Internal cycle: 4       Sistem: 98562   Position: [86.01591129976276 -51.36455324165249 0.9999999999999998 0 0 0]
        Internal cycle: 5       Sistem: 100610  Position: [80.0401030111902 -28.927947460228687 0.9999999999999999 0 0 0]
        Internal cycle: 6       Sistem: 65802   Position: [86.02466761227095 -51.363920733883326 1 0 0 0]
        Internal cycle: 7       Sistem: 67851   Position: [80.04638532334661 -28.92818591289178 1 0 0 0]

External cycle: 3 Star (valFixStar): ain
Memory Add. of FixStarCchar -> 0x101ad70
exit status 3221226356

Hope you can help me confront this problem, thanks anyway.

1 Answers

I thought that by freeing memory with C.Free (unsafe.Pointer ()) it would work, but it fails. It returns "could not determine kind of name for C.Free".


C.Free is not the same as C.free.


For example, from the documentation:

package main

// #include <stdio.h>
// #include <stdlib.h>
//
// static void myprint(char* s) {
//   printf("%s\n", s);
// }
import "C"
import "unsafe"

func main() {
    cs := C.CString("Hello from stdio")
    C.myprint(cs)
    C.free(unsafe.Pointer(cs))
}

Output:

Hello from stdio

Command cgo



Comment: I changed the code. Now it works a little better. Before, it failed the first cycle. Now in the third. I need it to reach 500 cycles – Jumanyi


The exit status 3221226356 message is likely an indication of memory corruption. Amongst other things, your calls to C.swe_fixstar_ut look suspicious.


If you hide the cgo C API implementation inside Go functions it's more robust and more readable. For example, some scribbled, untested code:

package main

/*
#cgo CFLAGS: -I C:/Users/peter/astro
#cgo LDFLAGS: -L C:/Users/peter/astro -lswedll64
#include "swephexp.h"
*/
import "C"

import (
    "errors"
    "strconv"
)

type SweErr struct {
    Code int32
    Err  error
}

func (e SweErr) Error() string {
    return strconv.Itoa(int(e.Code)) + ": " + e.Err.Error()
}

func SweFixstarUt(star string, tjd float64, iflag int32) (name string, xx []float64, rc int32, err error) {

    // Programming interface to the Swiss Ephemeris
    // https://www.astro.com/swisseph/swephprg.htm
    // 3.5. Error handling and return values
    // 5. Fixed stars functions
    // 5.2. swe_fixstar2_ut(), swe_fixstar2(), swe_fixstar_ut(), swe_fixstar()

    var swe struct {
        rc     C.int32
        star   [C.AS_MAXCH + 1]C.char
        tjd_ut C.double
        iflag  C.int32
        xx     [6]C.double
        serr   [C.AS_MAXCH + 1]C.char
    }

    if len(star) > len(swe.star)-1 {
        star = star[:len(swe.star)-1]
    }
    for i := 0; i < len(star); i++ {
        swe.star[i] = C.char(star[i])
    }
    swe.star[len(star)] = 0
    swe.tjd_ut = C.double(tjd)
    swe.iflag = C.int32(iflag)

    swe.rc = C.swe_fixstar_ut(
        &swe.star[0], swe.tjd_ut, swe.iflag, &swe.xx[0], &swe.serr[0],
    )
    swe.star[len(swe.star)-1] = 0
    swe.serr[len(swe.serr)-1] = 0

    if swe.rc < 0 {
        err := SweErr{
            Code: int32(swe.rc),
            Err:  errors.New(C.GoString(&swe.serr[0])),
        }
        return "", nil, 0, err
    }

    name = C.GoString(&swe.star[0])
    xx = make([]float64, len(swe.xx))
    for i := range xx {
        xx[i] = float64(swe.xx[i])
    }
    rc = int32(swe.rc)
    return name, xx, rc, nil
}

func main() {}

References:

Programming interface to the Swiss Ephemeris

The C Programming Language, 2nd Edition

The Go Programming Language

Related