add debug memory monitoring

This commit is contained in:
Hayden Johnson 2026-02-19 20:38:25 -08:00
parent 7562fd3043
commit 0adeba4daa
2 changed files with 59 additions and 7 deletions

View file

@ -2,6 +2,7 @@
---------------- ----------------
Phase 10 Tracker Phase 10 Tracker
---------------- ----------------
Author: Hayden Johnson
This program helps the user keep track of a game of Phase 10 as it is being This program helps the user keep track of a game of Phase 10 as it is being
played. It will keep track of players and their scores over the course of the played. It will keep track of players and their scores over the course of the
@ -14,9 +15,36 @@
*/ */
package phase10 package phase10
import "core:os"
import "core:fmt" import "core:fmt"
import "core:mem"
main :: proc() { main :: proc() {
// Memory tracking when building in debug mode
when ODIN_DEBUG {
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
defer {
if len(track.allocation_map) > 0 {
fmt.eprintf(
"=== %v allocations not freed: ===\n",
len(track.allocation_map)
)
for _, entry in track.allocation_map {
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
}
}
mem.tracking_allocator_destroy(&track)
}
}
// TODO don't just test this, actually read the fields into a game struct
if len(os.args) > 1 {
importGame(nil, os.args[1])
}
// Prompt for names // Prompt for names
buf: [2048]byte buf: [2048]byte
names := getNames(buf[:]) names := getNames(buf[:])
@ -40,13 +68,11 @@ main :: proc() {
winner = checkWinner(&game) winner = checkWinner(&game)
} }
// Print winner // Print winner and export game
fmt.printfln( fmt.printfln(
"%v wins! They had %v points!", "%v wins! They had %v points!",
game.names[winner], game.names[winner],
getScore(&game, winner) getScore(&game, winner)
) )
exportGame(&game, "game.csv") exportGame(&game, "game.csv")
} }

View file

@ -137,7 +137,11 @@ getNames :: proc(backingBuffer: []byte) -> []string {
// export a game as a csv // export a game as a csv
exportGame :: proc(game: ^Game, filename: string) { exportGame :: proc(game: ^Game, filename: string) {
// Open handle to file // Open handle to file
handle, err := os.open(filename, flags = os.O_CREATE | os.O_WRONLY | os.O_TRUNC, mode = 0o666) handle, err := os.open(
filename,
flags = os.O_CREATE | os.O_WRONLY | os.O_TRUNC,
mode = 0o644
)
if err != nil { if err != nil {
fmt.eprintln("Could not open file:", filename) fmt.eprintln("Could not open file:", filename)
return return
@ -152,6 +156,8 @@ exportGame :: proc(game: ^Game, filename: string) {
w: csv.Writer w: csv.Writer
csv.writer_init(&w, stream) csv.writer_init(&w, stream)
// We will store all rows as slices of strings. We will be allocating
// memory for the strings, so we need to free that memory too.
records: [dynamic][]string records: [dynamic][]string
defer { defer {
for record in records { for record in records {
@ -189,7 +195,27 @@ exportGame :: proc(game: ^Game, filename: string) {
} }
// import an existing game from a csv file // import an existing game from a csv file
importGame :: proc(filename: string) -> ^Game { importGame :: proc(game: ^Game, filename: string) {
// TODO r: csv.Reader
return nil r.trim_leading_space = true
r.reuse_record = true
r.reuse_record_buffer = true
defer csv.reader_destroy(&r)
csv_data, success := os.read_entire_file(filename, context.allocator)
defer delete(csv_data)
if success == true {
csv.reader_init_with_string(&r, string(csv_data))
} else {
fmt.eprintfln("Unable to open file: %v", filename)
return
}
for r, i, err in csv.iterator_next(&r) {
if err != nil { /* Do something with error */ }
for f, j in r {
fmt.printfln("Record %v, field %v: %q", i, j, f)
}
}
} }