fix: 修复AliveHosts全局变量内存泄漏问题

- 重构CheckLive函数使用局部变量代替全局变量
- 预分配容量避免频繁扩容提升性能
- 移除全局AliveHosts和ExistHosts变量声明
- 更新AliveScanner以使用局部存活主机列表
- 修复多次调用时内存累积问题
This commit is contained in:
ZacharyZcR 2025-08-07 10:08:46 +08:00
parent 78b8ff4f81
commit b38684bc9e
2 changed files with 28 additions and 30 deletions

View File

@ -31,6 +31,7 @@ type AliveStats struct {
DeadHosts int // 死亡主机数
ScanDuration time.Duration // 扫描耗时
SuccessRate float64 // 成功率
AliveHostList []string // 存活主机列表
}
// NewAliveScanStrategy 创建新的存活探测扫描策略
@ -95,12 +96,6 @@ func (s *AliveScanStrategy) performAliveScan(info common.HostInfo) {
common.LogBase(i18n.GetText("scan_alive_multiple_targets", len(hosts), hosts[0]))
}
// 清空之前的存活主机记录
AliveHosts = nil
for k := range ExistHosts {
delete(ExistHosts, k)
}
// 执行存活检测
aliveList := CheckLive(hosts, false) // 使用ICMP探测
@ -108,6 +103,7 @@ func (s *AliveScanStrategy) performAliveScan(info common.HostInfo) {
s.stats.AliveHosts = len(aliveList)
s.stats.DeadHosts = s.stats.TotalHosts - s.stats.AliveHosts
s.stats.ScanDuration = time.Since(s.startTime)
s.stats.AliveHostList = aliveList // 存储存活主机列表
if s.stats.TotalHosts > 0 {
s.stats.SuccessRate = float64(s.stats.AliveHosts) / float64(s.stats.TotalHosts) * 100
@ -134,7 +130,7 @@ func (s *AliveScanStrategy) outputStats() {
common.LogBase("")
common.LogBase(i18n.GetText("scan_alive_hosts_list"))
for i, host := range AliveHosts {
for i, host := range s.stats.AliveHostList {
common.LogSuccess(fmt.Sprintf(" [%d] %s", i+1, host))
}
}

View File

@ -16,25 +16,27 @@ import (
)
var (
AliveHosts []string // 存活主机列表
ExistHosts = make(map[string]struct{}) // 已发现主机记录
livewg sync.WaitGroup // 存活检测等待组
)
// CheckLive 检测主机存活状态
func CheckLive(hostslist []string, Ping bool) []string {
// 创建局部存活主机列表,预分配容量避免频繁扩容
aliveHosts := make([]string, 0, len(hostslist))
existHosts := make(map[string]struct{}, len(hostslist))
// 创建主机通道
chanHosts := make(chan string, len(hostslist))
// 处理存活主机
go handleAliveHosts(chanHosts, hostslist, Ping)
go handleAliveHosts(chanHosts, hostslist, Ping, &aliveHosts, existHosts)
// 根据Ping参数选择检测方式
if Ping {
// 使用ping方式探测
RunPing(hostslist, chanHosts)
} else {
probeWithICMP(hostslist, chanHosts)
probeWithICMP(hostslist, chanHosts, &aliveHosts)
}
// 等待所有检测完成
@ -42,9 +44,9 @@ func CheckLive(hostslist []string, Ping bool) []string {
close(chanHosts)
// 输出存活统计信息
printAliveStats(hostslist)
printAliveStats(aliveHosts, hostslist)
return AliveHosts
return aliveHosts
}
// IsContain 检查切片中是否包含指定元素
@ -57,11 +59,11 @@ func IsContain(items []string, item string) bool {
return false
}
func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool, aliveHosts *[]string, existHosts map[string]struct{}) {
for ip := range chanHosts {
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
ExistHosts[ip] = struct{}{}
AliveHosts = append(AliveHosts, ip)
if _, ok := existHosts[ip]; !ok && IsContain(hostslist, ip) {
existHosts[ip] = struct{}{}
*aliveHosts = append(*aliveHosts, ip)
// 使用Output系统保存存活主机信息
protocol := "ICMP"
@ -90,11 +92,11 @@ func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
}
// probeWithICMP 使用ICMP方式探测
func probeWithICMP(hostslist []string, chanHosts chan string) {
func probeWithICMP(hostslist []string, chanHosts chan string, aliveHosts *[]string) {
// 尝试监听本地ICMP
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err == nil {
RunIcmp1(hostslist, conn, chanHosts)
RunIcmp1(hostslist, conn, chanHosts, aliveHosts)
return
}
@ -134,13 +136,13 @@ func getOptimalTopCount(totalHosts int) int {
}
// printAliveStats 打印存活统计信息
func printAliveStats(hostslist []string) {
func printAliveStats(aliveHosts []string, hostslist []string) {
// 智能计算显示数量
topCount := getOptimalTopCount(len(hostslist))
// 大规模扫描时输出 /16 网段统计
if len(hostslist) > 1000 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, topCount, true)
arrTop, arrLen := ArrayCountValueTop(aliveHosts, topCount, true)
for i := 0; i < len(arrTop); i++ {
common.LogInfo(i18n.GetText("subnet_16_alive", arrTop[i], arrLen[i]))
}
@ -148,7 +150,7 @@ func printAliveStats(hostslist []string) {
// 输出 /24 网段统计
if len(hostslist) > 256 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, topCount, false)
arrTop, arrLen := ArrayCountValueTop(aliveHosts, topCount, false)
for i := 0; i < len(arrTop); i++ {
common.LogInfo(i18n.GetText("subnet_24_alive", arrTop[i], arrLen[i]))
}
@ -156,7 +158,7 @@ func printAliveStats(hostslist []string) {
}
// RunIcmp1 使用ICMP批量探测主机存活(监听模式)
func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string) {
func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string, aliveHosts *[]string) {
endflag := false
// 启动监听协程
@ -186,7 +188,7 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string)
start := time.Now()
for {
// 所有主机都已响应则退出
if len(AliveHosts) == len(hostslist) {
if len(*aliveHosts) == len(hostslist) {
break
}