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--

相关推荐
HEJOO913 小时前
Java 并发运行中的安全问题详解
java·开发语言
星夜离尘5614 小时前
MATLAB阶跃响应怎么量:别把最后一个采样点当成稳态
开发语言·matlab
云水初14 小时前
【agent篇】RAG Agent避坑指南(附高级RAG Agent汇总)
开发语言·笔记·python·学习·langchain·agent·rag
Littlehero_12114 小时前
QT自定义控件之水泥厂组态(源码开源)
开发语言·qt
辛苦才能14 小时前
C++ 哈希表深度解析:删除为什么必须打标记,负载因子为什么卡 0.7
开发语言·数据结构·c++·算法
miller-tsunami14 小时前
STL简介&string相关知识点
开发语言·c++·string
半摆烂日常15 小时前
手机表单的左滑操作:触摸事件的处理细节
大数据·开发语言·人工智能·智能手机·https·c#
星夜离尘5615 小时前
MATLAB滑动RMS如何接报警:窗口未满和缺样不能当成正常
开发语言·matlab
开开心心就好15 小时前
白天晚上自动调蓝光,护眼工具亮度可调
服务器·开发语言·算法·pdf·ocr·intellij-idea·idea
张张123y15 小时前
后端第十一课:RAG 落地实战(从 0 到 1 接上私有知识库,并设计一个好用的 RAG)
开发语言·人工智能·python·机器学习·fastapi·rag