Golang中如何解决Signal SIGSEGV: segmentation violation code=0x1错误

Golang中如何解决Signal SIGSEGV: segmentation violation code=0x1错误

shmid, _, err := syscall.Syscall(syscall.SYS_SHMGET, uintptr(10001), 1<<32, IpcCreate|0600)
data_shmaddr, _, _ := syscall.Syscall(syscall.SYS_SHMAT, shmid, 0, 0)
C.memcpy(unsafe.Pointer(data_shmaddr+uintptr(per_offs)), unsafe.Pointer((C.CString)(string(*data))), C.ulong(len(*data)))

我想使用memcpy将’data’复制到共享内存中,但似乎无法将地址从data_shmaddr映射到(data_shmaddr+1<<32)。 以下是遇到的错误: 致命错误:运行时发生意外信号 [信号SIGSEGV:分段违规 code=0x1 addr=0x7fe3502cca80 pc=0x7fe34d9320b4]

运行时堆栈: runtime.throw(0x552be5, 0x2a) /data1/user1/go_env/go/src/runtime/panic.go:619 +0x81 runtime.sigpanic() /data1/user1/go_env/go/src/runtime/signal_unix.go:372 +0x28e

goroutine 1 [syscall]: runtime.cgocall(0x4fe960, 0xc4200edd40, 0x29) /data1/user1/go_env/go/src/runtime/cgocall.go:128 +0x64 fp=0xc4200edd00 sp=0xc4200edcc8 pc=0x403034 main._Cfunc_memcpy(0x7fe3502cca80, 0x7fe3440008c0, 0x1, 0x0) _cgo_gotypes.go:78 +0x4e fp=0xc4200edd40 sp=0xc4200edd00 pc=0x4fdb7e main.(*MemPoolMng).PutData.func1(0x7fe3502cca80, 0x7fe3440008c0, 0x1, 0x1) /data1/user2/GoServer/mempool_go/mempool_mgr.go:107 +0x99 fp=0xc4200edd78 sp=0xc4200edd40 pc=0x4fe7a9 main.(*MemPoolMng).PutData(0xc4200182d0, 0xc420158000, 0xf4240) /data1/user2/GoServer/mempool_go/mempool_mgr.go:107 +0x1da fp=0xc4200ede58 sp=0xc4200edd78 pc=0x4fe37a main.handleProtoClient(0x565720, 0xc42000e060) /data1/user2/GoServer/mempool_go/server.go:58 +0x16f fp=0xc4200eded0 sp=0xc4200ede58 pc=0x4fcf8f main.main() /data1/user2/GoServer/mempool_go/server.go:39 +0x261 fp=0xc4200edf88 sp=0xc4200eded0 pc=0x4fcca1 runtime.main() /data1/user1/go_env/go/src/runtime/proc.go:198 +0x212 fp=0xc4200edfe0 sp=0xc4200edf88 pc=0x42b772 runtime.goexit() /data1/user1/go_env/go/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc4200edfe8 sp=0xc4200edfe0 pc=0x455601 退出状态2

有人能帮帮我吗?


更多关于Golang中如何解决Signal SIGSEGV: segmentation violation code=0x1错误的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

如果您能展示完整的程序而不仅仅是一个片段,可能会更有帮助。您对 IpcCreate 使用了什么?您是如何声明 data 的?

在不了解这些信息的情况下,我基于您的示例进行了处理。我有以下代码:

package main

//#include <stdio.h>
//#include <string.h>
//#include <sys/ipc.h>
//#include <sys/shm.h>
//void *memcpy(void *dest, const void *src, size_t n);
//int printf(const char *format, ...);
//#define BUFSIZE 32
//void dump(char *p)
//{
//      int i;
//      for(i = 0; i < BUFSIZE; i++)
//              printf("%d: %d\n",i,p[i]);
//      printf("\n");
//}
import "C"

import (
        "fmt"
        "os"
        "syscall"
        "unsafe"
        )

const bufsize int = 32
const offset = 10

var IpcCreate uintptr
var per_offs int = offset
var buf [bufsize]byte
var data *[bufsize]byte

// a tag so we can recognize if it's copying properly
const tagsize int = 10
const tag byte = 42

func main() {
        data = &buf
        IpcCreate = C.IPC_CREAT

        shmid, _, err := syscall.Syscall(syscall.SYS_SHMGET, uintptr(10001), 1<<32, IpcCreate|0600)
        if err != 0 {
                fmt.Fprintf(os.Stderr,"Cannot get shared memory. Error %d\n", err)
                os.Exit(1)
        }
        data_shmaddr, _, err := syscall.Syscall(syscall.SYS_SHMAT, shmid, 0, 0)
        if err != 0 {
                fmt.Fprintf(os.Stderr,"Cannot attach to shared memory. Error %d\n", err)
                os.Exit(1)
        }

        // write the tag into the buffer

        for i := 0; i < tagsize; i++ { buf[i] = tag }

        // copy the buffer into the shared memory, starting at byte 10

        C.memcpy(unsafe.Pointer(data_shmaddr+uintptr(per_offs)),
                 unsafe.Pointer(data), C.ulong(len(*data)))

        // dump data[]
        // this shows that 42 is in locations 0-9

        fmt.Printf("\n")
        fmt.Printf("data:\n")
        C.dump(C.CString(string((*data)[:])))

        // dump bufsize bytes of shared memory area
        // this shows that 42 is in locations 10-19

        fmt.Printf("shared memory:\n")
        C.dump((*C.char)(unsafe.Pointer(uintptr(data_shmaddr))))
}

我认为这段代码实现了您想要的功能。如果没有,那么请更清楚地说明您的问题。

提醒大家:此程序使用了 Cgo 以及 unsafesyscall 包。因此不要期望它具有跨平台兼容性。如果您有 Linux 系统,可以尝试运行它。

更多关于Golang中如何解决Signal SIGSEGV: segmentation violation code=0x1错误的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


SIGSEGV错误通常是由于无效的内存访问引起的。在你的代码中,问题可能出现在共享内存地址的计算和C.memcpy的使用上。以下是具体的分析和解决方案:

问题分析

  1. 共享内存大小问题1<<32 是4GB,这可能超出了系统限制
  2. 地址计算错误data_shmaddr+uintptr(per_offs) 可能导致无效地址
  3. 内存边界检查缺失:没有验证共享内存的有效范围

解决方案

package main

/*
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
*/
import "C"
import (
    "syscall"
    "unsafe"
)

const (
    IpcCreate = 0x200
)

func main() {
    // 1. 使用更合理的共享内存大小
    shmid, _, err := syscall.Syscall(syscall.SYS_SHMGET, uintptr(10001), 1<<20, // 1MB instead of 4GB
        uintptr(IpcCreate|0600))
    if err != 0 {
        // 处理错误
        return
    }

    // 2. 附加共享内存段
    data_shmaddr, _, err := syscall.Syscall(syscall.SYS_SHMAT, shmid, 0, 0)
    if err != 0 {
        // 处理错误
        return
    }

    // 3. 确保数据不会超出共享内存边界
    data := []byte("test data")
    per_offs := uintptr(0) // 确保偏移量在有效范围内
    
    // 4. 安全的memcpy调用
    if per_offs+uintptr(len(data)) <= 1<<20 { // 检查边界
        C.memcpy(unsafe.Pointer(data_shmaddr+per_offs), 
                unsafe.Pointer(&data[0]), 
                C.ulong(len(data)))
    }

    // 5. 使用完成后分离共享内存
    syscall.Syscall(syscall.SYS_SHMDT, data_shmaddr, 0, 0)
}

更安全的替代方案

考虑使用Go的标准库来处理共享内存:

import (
    "golang.org/x/sys/unix"
)

func safeSharedMemoryExample() {
    // 创建共享内存文件描述符
    fd, err := unix.MemfdCreate("mempool", 0)
    if err != nil {
        panic(err)
    }
    
    // 设置共享内存大小
    err = unix.Ftruncate(fd, 1<<20) // 1MB
    if err != nil {
        panic(err)
    }
    
    // 映射到内存
    data, err := unix.Mmap(fd, 0, 1<<20, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
    if err != nil {
        panic(err)
    }
    
    // 安全地复制数据
    copy(data, []byte("your data here"))
    
    // 清理
    unix.Munmap(data)
    unix.Close(fd)
}

关键改进点

  1. 减少共享内存大小:从4GB改为更合理的1MB
  2. 添加边界检查:确保不会访问超出分配范围的内存
  3. 错误处理:检查系统调用的返回值
  4. 资源清理:使用后正确分离共享内存

主要问题很可能是1<<32的大小超出了系统限制,或者per_offs的值导致了无效的内存地址计算。

回到顶部