1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

builtin: fix arrays/slices memory bug (#10219)

This commit is contained in:
Uwe Krüger 2021-05-27 14:50:06 +02:00 committed by GitHub
parent 25645dbc44
commit 8828054e5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 13 deletions

View File

@ -10,9 +10,10 @@ pub struct array {
pub: pub:
element_size int // size in bytes of one element in the array. element_size int // size in bytes of one element in the array.
pub mut: pub mut:
data voidptr data voidptr
len int // length of the array. offset int // in bytes (should be `size_t`)
cap int // capacity of the array. len int // length of the array.
cap int // capacity of the array.
} }
// array.data uses a void pointer, which allows implementing arrays without generics and without generating // array.data uses a void pointer, which allows implementing arrays without generics and without generating
@ -95,11 +96,13 @@ fn (mut a array) ensure_cap(required int) {
cap *= 2 cap *= 2
} }
new_size := cap * a.element_size new_size := cap * a.element_size
a.data = if a.data != voidptr(0) { new_data := vcalloc(new_size)
unsafe { realloc_data(a.data, a.cap * a.element_size, new_size) } if a.data != voidptr(0) {
} else { unsafe { C.memcpy(new_data, a.data, a.len * a.element_size) }
vcalloc(new_size) // TODO: the old data may be leaked when no GC is used (ref-counting?)
} }
a.data = new_data
a.offset = 0
a.cap = cap a.cap = cap
} }
@ -307,14 +310,13 @@ fn (a array) slice(start int, _end int) array {
panic('array.slice: slice bounds out of range ($start < 0)') panic('array.slice: slice bounds out of range ($start < 0)')
} }
} }
mut data := &byte(0) offset := start * a.element_size
unsafe { data := unsafe { &byte(a.data) + offset }
data = &byte(a.data) + start * a.element_size
}
l := end - start l := end - start
res := array{ res := array{
element_size: a.element_size element_size: a.element_size
data: data data: data
offset: a.offset + offset
len: l len: l
cap: l cap: l
} }
@ -384,13 +386,15 @@ fn (a &array) slice_clone(start int, _end int) array {
} }
} }
mut data := &byte(0) mut data := &byte(0)
offset := start * a.element_size
unsafe { unsafe {
data = &byte(a.data) + start * a.element_size data = &byte(a.data) + offset
} }
l := end - start l := end - start
res := array{ res := array{
element_size: a.element_size element_size: a.element_size
data: data data: data
offset: offset
len: l len: l
cap: l cap: l
} }
@ -484,7 +488,7 @@ pub fn (a &array) free() {
// if a.is_slice { // if a.is_slice {
// return // return
// } // }
unsafe { free(a.data) } unsafe { free(&byte(a.data) - a.offset) }
} }
[unsafe] [unsafe]

View File

@ -60,3 +60,22 @@ fn test_pointer_array_slice() {
mut arr := [1, 2, 3] mut arr := [1, 2, 3]
pointer_array_slice(mut arr) pointer_array_slice(mut arr)
} }
fn test_push_to_orig() {
mut orig := [1, 2, 3, 4]
slice := orig[1..3]
for _ in 0 .. 1000 {
orig << 9
}
orig[2] = 7
slice2 := orig[1..3]
assert slice == [2, 3] || slice == [2, 7]
assert slice2 == [2, 7]
}
fn test_self_slice_push() {
mut a := [1, 2, 3]
a = a[1..]
a << 4
assert a == [2, 3, 4]
}