golang将指针传给cgo后还能被回收吗?

问题:

如果把golang分配的变量,其指针通过cgo传给c,并被c存储,那这个变量还能被gc回收吗?

实验代码:

test_memory_leak.go

Go 复制代码
package main

/*
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char* cMalloc() {
	char *mem = (char*)malloc(1024 * 1024 * 16);
	return mem;
}

void cMemset(char* mem) {
	memset(mem, '-', 1024 * 1024 * 16);
}

int arrLen = 1000;
int arrIndex;
char* globalMemAddr[1000];

void printAddr(char* mem) {
	if (arrIndex+1 >= arrLen) {
		arrIndex = 0;
	} else {
		arrIndex++;
	}
	globalMemAddr[arrIndex] = mem;
	printf("index: %d, addr: %p\n", arrIndex, globalMemAddr[arrIndex]);
}
*/
import "C"
import (
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"os"
	"sync"
	"time"
	"unsafe"
)

var size int = 1024 * 1024 * 16

func main() {
	go func() {
		_ = http.ListenAndServe("0.0.0.0:9091", nil)
	}()
	if len(os.Args) > 1 && os.Args[1] == "1" {
		var wg sync.WaitGroup
		for {
			wg.Add(1)
			go doCMalloc(&wg)
			wg.Wait()
			time.Sleep(500 * time.Millisecond)
		}
	} else {
		var wg sync.WaitGroup
		for {
			wg.Add(1)
			go doGoMalloc(&wg)
			wg.Wait()
			time.Sleep(500 * time.Millisecond)
		}
	}
}

// 无泄漏
func doCMalloc(wg *sync.WaitGroup) {
	defer wg.Done()
	cptr := C.cMalloc()
	C.cMemset(cptr)
	C.printAddr(cptr)
	bs := C.GoBytes(unsafe.Pointer(cptr), C.int(size))
	fmt.Printf("1: %s .. %s\n", string(bs[0:8]), string(bs[size-8:size]))
	C.free(unsafe.Pointer(cptr))
}

// 无泄漏
func doGoMalloc(wg *sync.WaitGroup) {
	defer wg.Done()
	bs := make([]byte, size, size)
	cptr := (*C.char)(unsafe.Pointer(&bs[0]))
	C.cMemset(cptr)
	C.printAddr(cptr)
	fmt.Printf("2: %s .. %s\n", string(bs[0:8]), string(bs[size-8:size]))
}

运行代码分支2:

GODEBUG=gctrace=1 ./test_memory_leak 2

终端显示:

top显示:

pprof数据:

go tool pprof -http=10.10.10.244:9000 http://127.0.0.1:9091/debug/pprof/allocs

alloc_objects:

inuse_space:

观察到的数据:

1、变量地址始终在0xc000180000和0xc001200000之间交换,说明内存被回收重复利用。

2、每次gc结束后内存始终控制在16MB。

3、进程使用的内存始终在40多MB,并没有太大变化。

4、inuse_space保持16MB不变,而alloc_objects在不断增长。

结论:

golang分配的变量,其指针被cgo引用,不影响golang对其进行垃圾回收。

--end--

相关推荐
南棱笑笑生几秒前
20251028在荣品RD-RK3588-MID开发板的Android13系统下解决关机的时候最近打开的应用不关的问题
开发语言·python·rockchip
AnalogElectronic1 小时前
vue3 实现贪吃蛇手机版01
开发语言·javascript·ecmascript
Momentary_SixthSense1 小时前
rust笔记
开发语言·笔记·rust
多多*1 小时前
Spring Bean的生命周期 第二次思考
java·开发语言·rpc
大飞pkz1 小时前
【算法】排序算法汇总1
开发语言·数据结构·算法·c#·排序算法
Swift社区2 小时前
Foundation Model 在 Swift 中的类型安全生成实践
开发语言·安全·swift
草明2 小时前
当 Go 的 channel 被 close 后读写操作会怎么样?
开发语言·后端·golang
AI_56782 小时前
脑科学支持的Python学习法:每天2小时碎片化训练,用‘神经可塑性’打败拖延症“
开发语言·python·学习
前端世界2 小时前
当网络里混入“假网关”:用 Scapy 写一个 DHCP 欺骗检测器(附完整代码与讲解)
开发语言·网络·php
千里镜宵烛2 小时前
Lua-编译,执行和错误
开发语言·lua