Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions homeworks/11_garbage_collector/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Домашнее задание №11

В домашнем задании нужно реализовать функцию трассировки объектов.

Трассировка объектов будет осуществляться со стеков, рекурсивно проходя все объекты в куче. Важно написать реализацию алгоритма так, чтобы не было повторных обходов одних и тех же объектов. Циклов не будет, проверку на это реализовывать не нужно. Для обхода объектов можно использовать алгоритмы DFS или BFS.

Различать указатели и свободные участки памяти нужно будет при помощи значений в памяти, если значение непустое — значит это указатель, который указывает на какой-то другой участок памяти.

Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по [ссылке](https://github.com/Balun-courses/deep_go/blob/master/homework/garbage_collector/homework_test.go)

Задание со звездочкой
Выполнять необязательно, но можно попробовать реализовать функцию трассировки объектов, которая будет учитывать циклы, используя алгоритм раскраски вершин, либо несколько множеств посещеных вершин.
85 changes: 85 additions & 0 deletions homeworks/11_garbage_collector/homework_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"testing"
"unsafe"

"github.com/stretchr/testify/assert"
)

// go test -v homework_test.go

func Trace(stacks [][]uintptr) []uintptr {
seen := map[uintptr]bool{}
result := []uintptr{}

var dfs func(ptr uintptr)
dfs = func(ptr uintptr) {
if ptr == 0 || seen[ptr] {
return
}
seen[ptr] = true
result = append(result, ptr)

//nolint:govet
uptr := *(*uintptr)(unsafe.Pointer(ptr))
dfs(uptr)
}

for _, row := range stacks {
for _, ptr := range row {
dfs(ptr)
}
}
return result

}

// For test purpose we want to allocate this globally
var heapObjects = []int{
0x00, 0x00, 0x00, 0x00, 0x00,
}

var (
heapPointer1 = &heapObjects[1]
heapPointer2 = &heapObjects[2]
heapPointer3 = (*int)(nil)
heapPointer4 = &heapPointer3
)

func TestTrace(t *testing.T) {

var stacks = [][]uintptr{
{
uintptr(unsafe.Pointer(&heapPointer1)), 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[0])),
0x00, 0x00, 0x00, 0x00,
},
{
uintptr(unsafe.Pointer(&heapPointer2)), 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[1])),
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[2])),
uintptr(unsafe.Pointer(&heapPointer4)), 0x00, 0x00, 0x00,
},
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, uintptr(unsafe.Pointer(&heapObjects[3])),
},
}

pointers := Trace(stacks)
expectedPointers := []uintptr{
uintptr(unsafe.Pointer(&heapPointer1)),
uintptr(unsafe.Pointer(&heapObjects[0])),
uintptr(unsafe.Pointer(&heapPointer2)),
uintptr(unsafe.Pointer(&heapObjects[1])),
uintptr(unsafe.Pointer(&heapObjects[2])),
uintptr(unsafe.Pointer(&heapPointer4)),
uintptr(unsafe.Pointer(&heapPointer3)),
uintptr(unsafe.Pointer(&heapObjects[3])),
}
assert.ElementsMatch(t, expectedPointers, pointers)
}