求助:Odin语言传递动态数组给函数后前两元素损坏
问题
我正在学习Odin语言以完成Advent of Code,在函数中逐行读取文件时遇到了问题。我尝试过按值返回数组和返回切片,但都出现了同样的问题:数组的前两个元素被随机垃圾数据损坏。
我的代码
package main import "core:os" import "core:fmt" import "core:slice" import "core:strings" read_file_line_by_line :: proc(filepath: string, lines: ^[dynamic]string ) { data, ok := os.read_entire_file(filepath, context.allocator) defer delete(data, context.allocator) it := string(data) fmt.println( "As the array is built...") for line in strings.split_lines_iterator(&it) { append( lines, line ) fmt.println( line ) } fmt.println( "After the array is built...") for line in lines { fmt.printf( "%s\n", line ) } } main :: proc() { if len(os.args) < 2 { fmt.eprintf( "Usage: %s <filename>\n", os.args[ 0 ] ) return } lines : [dynamic]string read_file_line_by_line( os.args[ 1 ], &lines ) fmt.println( "After the array is returned...") for line in lines { fmt.println( line ) } }
输入文件内容
L68 L30 R48 L5 R60 L55 L1 L99 R14 L82
输出结果
As the array is built... L68 L30 R48 L5 R60 L55 L1 L99 R14 L82 After the array is built... L68 L30 R48 L5 R60 L55 L1 L99 R14 L82 After the array is returned... �` << Corrupted element �f� << Corrupted element R48 L5 R60 L55 L1 L99 R14 L82
解决方案
问题核心是:strings.split_lines_iterator返回的是原文件数据的子切片,而你在函数中用defer delete(data, context.allocator)在函数结束后释放了原始文件内存。函数内部遍历数组时,原始内存还未被回收,所以内容正常;但函数返回后,原始内存被系统回收并覆盖,导致数组中存储的字符串指针指向无效内存,出现垃圾数据。
修正方案是给每行字符串创建独立的内存副本,脱离原始数据的生命周期限制。
修正后的代码
package main import "core:os" import "core:fmt" import "core:slice" import "core:strings" read_file_line_by_line :: proc(filepath: string, lines: ^[dynamic]string ) { data, ok := os.read_entire_file(filepath, context.allocator) defer delete(data, context.allocator) it := string(data) fmt.println( "As the array is built...") for line in strings.split_lines_iterator(&it) { // 复制字符串到新内存,避免依赖原始数据的生命周期 line_copy := strings.duplicate(line, context.allocator) append( lines, line_copy ) fmt.println( line ) } fmt.println( "After the array is built...") for line in lines { fmt.printf( "%s\n", line ) } } main :: proc() { if len(os.args) < 2 { fmt.eprintf( "Usage: %s <filename>\n", os.args[ 0 ] ) return } lines : [dynamic]string defer { // 手动释放每个字符串的内存,避免内存泄漏 for line in lines { delete(line, context.allocator) } delete(lines, context.allocator) } read_file_line_by_line( os.args[ 1 ], &lines ) fmt.println( "After the array is returned...") for line in lines { fmt.println( line ) } }
关键改动说明
- 复制字符串:用
strings.duplicate(line, context.allocator)为每行创建独立内存副本,确保数组中的字符串不依赖原始文件数据的内存。 - 内存回收:在
main函数中添加defer块,遍历动态数组释放每个字符串的内存——Odin是手动内存管理语言,必须显式回收分配的内存,避免内存泄漏。
修改后,函数返回后数组中的所有字符串都会保留正确内容,不会出现内存损坏问题。
内容的提问来源于stack exchange,提问作者Commodore63
相关产品推荐
相关产品推荐

