From 226c69db6c9ea72bb7af86a36c07106ed32ea82e Mon Sep 17 00:00:00 2001 From: Vladislav Byrgazov Date: Sun, 11 Jan 2026 12:35:02 +0500 Subject: [PATCH 1/7] homework: implement tracing dfs func Signed-off-by: Vladislav Byrgazov --- homeworks/11_garbage_collector/README.md | 12 +++ .../11_garbage_collector/homework_test.go | 79 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 homeworks/11_garbage_collector/README.md create mode 100644 homeworks/11_garbage_collector/homework_test.go diff --git a/homeworks/11_garbage_collector/README.md b/homeworks/11_garbage_collector/README.md new file mode 100644 index 0000000..db6adfe --- /dev/null +++ b/homeworks/11_garbage_collector/README.md @@ -0,0 +1,12 @@ +# Домашнее задание №11 + +В домашнем задании нужно реализовать функцию трассировки объектов. + +Трассировка объектов будет осуществляться со стеков, рекурсивно проходя все объекты в куче. Важно написать реализацию алгоритма так, чтобы не было повторных обходов одних и тех же объектов. Циклов не будет, проверку на это реализовывать не нужно. Для обхода объектов можно использовать алгоритмы DFS или BFS. + +Различать указатели и свободные участки памяти нужно будет при помощи значений в памяти, если значение непустое — значит это указатель, который указывает на какой-то другой участок памяти. + +Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по [ссылке](https://github.com/Balun-courses/deep_go/blob/master/homework/garbage_collector/homework_test.go) + +Задание со звездочкой +Выполнять необязательно, но можно попробовать реализовать функцию трассировки объектов, которая будет учитывать циклы, используя алгоритм раскраски вершин, либо несколько множеств посещеных вершин. \ No newline at end of file diff --git a/homeworks/11_garbage_collector/homework_test.go b/homeworks/11_garbage_collector/homework_test.go new file mode 100644 index 0000000..d10fef5 --- /dev/null +++ b/homeworks/11_garbage_collector/homework_test.go @@ -0,0 +1,79 @@ +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(uintptr) + dfs = func(ptr uintptr) { + if ptr == 0 || seen[ptr] { + return + } + result = append(result, ptr) + seen[ptr] = true + next := *(*uintptr)(unsafe.Pointer(ptr)) + dfs(next) + } + + for _, row := range stacks { + for _, ptr := range row { + dfs(ptr) + } + + } + return result +} + +func TestTrace(t *testing.T) { + var heapObjects = []int{ + 0x00, 0x00, 0x00, 0x00, 0x00, + } + + var heapPointer1 *int = &heapObjects[1] + var heapPointer2 *int = &heapObjects[2] + var heapPointer3 *int = nil + var heapPointer4 **int = &heapPointer3 + + 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) +} From 40030760e748c72c9ae26efd25f4314d6df5e05d Mon Sep 17 00:00:00 2001 From: Vladislav Byrgazov Date: Sun, 11 Jan 2026 12:59:13 +0500 Subject: [PATCH 2/7] fix: pass unsafe.Pointer to dfs func Signed-off-by: Vladislav Byrgazov --- .../11_garbage_collector/homework_test.go | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/homeworks/11_garbage_collector/homework_test.go b/homeworks/11_garbage_collector/homework_test.go index d10fef5..692739d 100644 --- a/homeworks/11_garbage_collector/homework_test.go +++ b/homeworks/11_garbage_collector/homework_test.go @@ -13,20 +13,27 @@ func Trace(stacks [][]uintptr) []uintptr { seen := map[uintptr]bool{} result := []uintptr{} - var dfs func(uintptr) - dfs = func(ptr uintptr) { - if ptr == 0 || seen[ptr] { + var dfs func(ptr unsafe.Pointer) + dfs = func(ptr unsafe.Pointer) { + if ptr == nil { return } - result = append(result, ptr) - seen[ptr] = true - next := *(*uintptr)(unsafe.Pointer(ptr)) + uptr := uintptr(ptr) + if seen[uptr] { + return + } + result = append(result, uptr) + seen[uptr] = true + next := *(*unsafe.Pointer)(ptr) dfs(next) } for _, row := range stacks { for _, ptr := range row { - dfs(ptr) + if ptr == 0 { + continue + } + dfs(unsafe.Pointer(ptr)) } } From 93b4b71174a6724a82b85d243e8bbad582479791 Mon Sep 17 00:00:00 2001 From: Vladislav Byrgazov Date: Sun, 11 Jan 2026 13:14:05 +0500 Subject: [PATCH 3/7] fix: fix linter Signed-off-by: Vladislav Byrgazov --- homeworks/11_garbage_collector/homework_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/homeworks/11_garbage_collector/homework_test.go b/homeworks/11_garbage_collector/homework_test.go index 692739d..1cdd12c 100644 --- a/homeworks/11_garbage_collector/homework_test.go +++ b/homeworks/11_garbage_collector/homework_test.go @@ -33,6 +33,7 @@ func Trace(stacks [][]uintptr) []uintptr { if ptr == 0 { continue } + //nolint:govet dfs(unsafe.Pointer(ptr)) } @@ -45,10 +46,10 @@ func TestTrace(t *testing.T) { 0x00, 0x00, 0x00, 0x00, 0x00, } - var heapPointer1 *int = &heapObjects[1] - var heapPointer2 *int = &heapObjects[2] - var heapPointer3 *int = nil - var heapPointer4 **int = &heapPointer3 + heapPointer1 := &heapObjects[1] + heapPointer2 := &heapObjects[2] + heapPointer3 := (*int)(nil) + heapPointer4 := &heapPointer3 var stacks = [][]uintptr{ { From ed15d3bde7639c7b47c51d04d590787a1b64def5 Mon Sep 17 00:00:00 2001 From: Vladislav Byrgazov Date: Sun, 11 Jan 2026 13:22:44 +0500 Subject: [PATCH 4/7] fix: make sure ptr obj is alive Signed-off-by: Vladislav Byrgazov --- homeworks/11_garbage_collector/homework_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeworks/11_garbage_collector/homework_test.go b/homeworks/11_garbage_collector/homework_test.go index 1cdd12c..2664bbc 100644 --- a/homeworks/11_garbage_collector/homework_test.go +++ b/homeworks/11_garbage_collector/homework_test.go @@ -1,6 +1,7 @@ package main import ( + "runtime" "testing" "unsafe" @@ -24,8 +25,11 @@ func Trace(stacks [][]uintptr) []uintptr { } result = append(result, uptr) seen[uptr] = true + next := *(*unsafe.Pointer)(ptr) dfs(next) + + runtime.KeepAlive(ptr) } for _, row := range stacks { @@ -36,7 +40,6 @@ func Trace(stacks [][]uintptr) []uintptr { //nolint:govet dfs(unsafe.Pointer(ptr)) } - } return result } From 4aa516bbac945efde63d880422543d627e7654c8 Mon Sep 17 00:00:00 2001 From: Vladislav Byrgazov Date: Sun, 11 Jan 2026 13:40:54 +0500 Subject: [PATCH 5/7] fix: stabilise Signed-off-by: Vladislav Byrgazov --- .../11_garbage_collector/homework_test.go | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/homeworks/11_garbage_collector/homework_test.go b/homeworks/11_garbage_collector/homework_test.go index 2664bbc..a1e33bb 100644 --- a/homeworks/11_garbage_collector/homework_test.go +++ b/homeworks/11_garbage_collector/homework_test.go @@ -1,7 +1,6 @@ package main import ( - "runtime" "testing" "unsafe" @@ -14,31 +13,22 @@ func Trace(stacks [][]uintptr) []uintptr { seen := map[uintptr]bool{} result := []uintptr{} - var dfs func(ptr unsafe.Pointer) - dfs = func(ptr unsafe.Pointer) { - if ptr == nil { + var dfs func(ptr uintptr) + dfs = func(ptr uintptr) { + if ptr == 0 || seen[ptr] { return } - uptr := uintptr(ptr) - if seen[uptr] { - return - } - result = append(result, uptr) - seen[uptr] = true - - next := *(*unsafe.Pointer)(ptr) - dfs(next) + seen[ptr] = true + result = append(result, ptr) - runtime.KeepAlive(ptr) + //nolint:govet + uptr := *(*uintptr)(unsafe.Pointer(ptr)) + dfs(uptr) } for _, row := range stacks { for _, ptr := range row { - if ptr == 0 { - continue - } - //nolint:govet - dfs(unsafe.Pointer(ptr)) + dfs(ptr) } } return result From 3be6acc1e192d9cfd8544dd5fecf75f04585714e Mon Sep 17 00:00:00 2001 From: Vladislav Byrgazov Date: Sun, 11 Jan 2026 14:21:29 +0500 Subject: [PATCH 6/7] fix: allocate heap objects globally Signed-off-by: Vladislav Byrgazov --- homeworks/11_garbage_collector/homework_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/homeworks/11_garbage_collector/homework_test.go b/homeworks/11_garbage_collector/homework_test.go index a1e33bb..62a3628 100644 --- a/homeworks/11_garbage_collector/homework_test.go +++ b/homeworks/11_garbage_collector/homework_test.go @@ -32,13 +32,15 @@ func Trace(stacks [][]uintptr) []uintptr { } } return result + } -func TestTrace(t *testing.T) { - var heapObjects = []int{ - 0x00, 0x00, 0x00, 0x00, 0x00, - } +// For test purpose we want to allocate this globally +var heapObjects = []int{ + 0x00, 0x00, 0x00, 0x00, 0x00, +} +func TestTrace(t *testing.T) { heapPointer1 := &heapObjects[1] heapPointer2 := &heapObjects[2] heapPointer3 := (*int)(nil) From 7e822eabd27b4cd11d04731b30cb3d2e295e68f1 Mon Sep 17 00:00:00 2001 From: Vladislav Byrgazov Date: Sun, 11 Jan 2026 14:28:36 +0500 Subject: [PATCH 7/7] fix: move more vars to global scope Signed-off-by: Vladislav Byrgazov --- homeworks/11_garbage_collector/homework_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/homeworks/11_garbage_collector/homework_test.go b/homeworks/11_garbage_collector/homework_test.go index 62a3628..2812651 100644 --- a/homeworks/11_garbage_collector/homework_test.go +++ b/homeworks/11_garbage_collector/homework_test.go @@ -40,11 +40,14 @@ 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) { - heapPointer1 := &heapObjects[1] - heapPointer2 := &heapObjects[2] - heapPointer3 := (*int)(nil) - heapPointer4 := &heapPointer3 var stacks = [][]uintptr{ {