gpt4 book ai didi

c - C 中的指针从内存中删除

转载 作者:行者123 更新时间:2023-12-03 03:11:36 25 4
gpt4 key购买 nike

在这种情况下,我将指针从 Go 传递到 C 函数,C 函数修改该指针值(填充数组),然后我在 Go 代码中再次使用相同的指针,确保调用 C.free 在我完成后释放它。

有时在该指针上获得零引用,我很难理解为什么。

这里,Go中的对象是cpuTimesC,在C中是cputicks

我也尝试过让函数返回指针,结果相同。最奇怪的是,如果我在函数末尾放置 printf 语句,则需要更长的时间才能最终得到 nil 错误。

package collector

/*
#cgo LDFLAGS: -lperfstat
#include <stdlib.h>
#include <stdio.h>
#include <libperfstat.h>
#include <string.h>
#include <time.h>

u_longlong_t **ref;

int getCPUTicks(uint64_t **cputicks, size_t *cpu_ticks_len) {
int i, ncpus, cputotal;
perfstat_id_t firstcpu;
perfstat_cpu_t *statp;

cputotal = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
if (cputotal <= 0){
return -1;
}

statp = calloc(cputotal, sizeof(perfstat_cpu_t));
if(statp==NULL){
return -1;
}
ncpus = perfstat_cpu(&firstcpu, statp, sizeof(perfstat_cpu_t), cputotal);
*cpu_ticks_len = ncpus*4;

*cputicks = (uint64_t *) malloc(sizeof(uint64_t)*(*cpu_ticks_len));
for (i = 0; i < ncpus; i++) {
int offset = 4 * i;
(*cputicks)[offset] = statp[i].user;
(*cputicks)[offset+1] = statp[i].sys;
(*cputicks)[offset+2] = statp[i].wait;
(*cputicks)[offset+3] = statp[i].idle;
}
return 0;
}
*/
import "C"

import (
"errors"
"unsafe"
"fmt"
"github.com/prometheus/client_golang/prometheus"
)

const ClocksPerSec = float64(C.CLK_TCK)
const maxCPUTimesLen = 1024 * 4

type statCollector struct {
cpu *prometheus.Desc
}

func init() {
registerCollector("cpu", true, NewCPUCollector)
}

func NewCPUCollector() (Collector, error) {
return &statCollector{
cpu: nodeCPUSecondsDesc,
}, nil
}

func (c *statCollector) Update(ch chan<- prometheus.Metric) error {
var fieldsCount = 4
cpuFields := []string{"user", "sys", "wait", "idle"}

var (
cpuTimesC *C.uint64_t
cpuTimesLength C.size_t
)

if C.getCPUTicks(&cpuTimesC, &cpuTimesLength) == -1 {
return errors.New("could not retrieve CPU times")
}
defer C.free(unsafe.Pointer(cpuTimesC))
cput := (*[maxCPUTimesLen]C.u_longlong_t)(unsafe.Pointer(cpuTimesC))[:cpuTimesLength:cpuTimesLength]

cpuTicks := make([]float64, cpuTimesLength)
for i, value := range cput {
cpuTicks[i] = float64(value) / ClocksPerSec
}

for i, value := range cpuTicks {
cpux := fmt.Sprintf("CPU %d", i/fieldsCount)
ch <- prometheus.MustNewConstMetric(c.cpu, prometheus.CounterValue, value, cpux, cpuFields[i%fieldsCount])
}

return nil
}

错误是:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x33 addr=0x0 pc=0x1003fcec0]

goroutine 940 [running]:
github.com/dlopes7/aix-prometheus-exporter/collector.(*statCollector).Update(0xa000100000d21b8, 0xa0001000028c480, 0x0, 0x0)
/home/david/go/src/github.com/dlopes7/aix-prometheus-exporter/collector/cpu_aix.go:81 +0xf0
github.com/dlopes7/aix-prometheus-exporter/collector.execute(0x10043e7e7, 0x3, 0x1101120e0, 0xa000100000d21b8, 0xa0001000028c480)
/home/david/go/src/github.com/dlopes7/aix-prometheus-exporter/collector/collector.go:95 +0x6c
github.com/dlopes7/aix-prometheus-exporter/collector.AIXCollector.Collect.func1(0xa0001000028c480, 0xa000100000cd440, 0x10043e7e7, 0x3, 0x1101120e0, 0xa000100000d21b8)
/home/david/go/src/github.com/dlopes7/aix-prometheus-exporter/collector/collector.go:115 +0x4c
created by github.com/dlopes7/aix-prometheus-exporter/collector.AIXCollector.Collect
/home/david/go/src/github.com/dlopes7/aix-prometheus-exporter/collector/collector.go:114 +0xf8

我知道它发生在这里,因为由于某种原因 cpuTimesC 为零:

cput := (*[maxCPUTimesLen]C.u_longlong_t)(unsafe.Pointer(cpuTimesC))[:cpuTimesLength:cpuTimesLength]

为什么这个对象有时会为零,如何让它保留在内存中,直到我调用 C.free

这是在 AIX PPC64 上使用 cgo(如果有什么区别的话)。

最佳答案

这与从内存中删除指针无关,cputicks 为 NULL,因为 ncpus 为 -1,因此 malloc 调用返回 NULL,ncpu 为 -1,因为 perfstat_cpu 调用的第一个参数未正确初始化,添加:

strcpy(firstcpu.name, FIRST_CPU);

按照 @kostik 的建议,在调用 perfstat_cpu 修复问题之前

关于c - C 中的指针从内存中删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59236396/

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