// Как Go предотвращает Undefined Behavior
// Запуск: go run safety_demo.go

package main

import (
	"fmt"
	"math"
)

func main() {
	fmt.Println("=== Go: определённое поведение по умолчанию ===")
	fmt.Println()

	// 1. Целочисленное переполнение — определённое поведение (обёртка)
	fmt.Println("--- 1. Целочисленное переполнение ---")
	var x int32 = math.MaxInt32
	fmt.Printf("MaxInt32     = %d\n", x)
	fmt.Printf("MaxInt32 + 1 = %d (молчаливая обёртка — определённое поведение)\n", x+1)
	// Go не паникует. Переполнение определено как обёртка по модулю 2^n.
	// Это безопасно (нет UB), но может быть логической ошибкой.

	// Для безопасной арифметики — пакет math/bits или ручные проверки.
	fmt.Println()

	// 2. Nil — паника в рантайме, а не UB
	fmt.Println("--- 2. Nil-разыменование ---")
	// var p *int = nil
	// _ = *p // panic: runtime error: invalid memory address or nil pointer dereference
	fmt.Println("Разыменование nil → panic (определённое поведение)")
	fmt.Println("Не UB: стек-трейс, диагностика, recover().")
	fmt.Println()

	// 3. Сборка мусора: use-after-free невозможен
	fmt.Println("--- 3. Сборка мусора ---")
	s := make([]byte, 10)
	s[0] = 42
	// После s = nil объект будет собран GC.
	// Нет ручного free() → нет use-after-free.
	fmt.Println("GC управляет памятью. Ручной free() отсутствует.")
	fmt.Println("Use-after-free и double-free невозможны.")
	fmt.Println()

	// 4. Проверка границ массива
	fmt.Println("--- 4. Проверка границ ---")
	arr := [4]int{10, 20, 30, 40}
	fmt.Printf("arr = %v\n", arr)
	// arr[4] → panic: index out of range [4] with length 4
	fmt.Println("arr[4] → panic: index out of range")
	fmt.Println("Проверка границ выполняется в рантайме всегда.")
	fmt.Println()

	// 5. Слайсы: безопасный доступ
	fmt.Println("--- 5. Слайсы ---")
	slice := []int{10, 20, 30}
	if len(slice) > 5 {
		fmt.Println(slice[5])
	} else {
		fmt.Println("len(slice) = 3, доступ к [5] предотвращён проверкой длины")
	}
	fmt.Println()

	// 6. Data race detection (go run -race)
	fmt.Println("--- 6. Детектор гонок ---")
	fmt.Println("go run -race программа.go — обнаружит гонки данных в рантайме.")
	fmt.Println("В C/C++ гонка данных — это UB. В Go — определённое (но багнутое) поведение.")
	fmt.Println()

	fmt.Println("--- Итог ---")
	fmt.Println("Переполнение → обёртка (определённое поведение)")
	fmt.Println("Null → panic с трейсом (не UB)")
	fmt.Println("Память → GC (use-after-free невозможен)")
	fmt.Println("Границы → panic (проверка в рантайме)")
	fmt.Println("Гонки → детектор -race (диагностика)")
}
