builtin: implement `-d debug_realloc`

pull/8106/head
Delyan Angelov 2021-01-14 11:41:52 +02:00
parent aa878161e9
commit ca5f88eb7d
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
1 changed files with 52 additions and 39 deletions

View File

@ -77,25 +77,27 @@ pub fn panic(s string) {
// eprintln prints a message with a line end, to stderr. Both stderr and stdout are flushed. // eprintln prints a message with a line end, to stderr. Both stderr and stdout are flushed.
pub fn eprintln(s string) { pub fn eprintln(s string) {
// eprintln is used in panics, so it should not fail at all
if s.str == 0 {
eprintln('eprintln(NIL)')
}
C.fflush(C.stdout) C.fflush(C.stdout)
C.fflush(C.stderr) C.fflush(C.stderr)
C.write(2, s.str, s.len) // eprintln is used in panics, so it should not fail at all
C.write(2, c'\n', 1) if s.str == 0 {
C.write(2, c'eprintln(NIL)\n', 14)
} else {
C.write(2, s.str, s.len)
C.write(2, c'\n', 1)
}
C.fflush(C.stderr) C.fflush(C.stderr)
} }
// eprint prints a message to stderr. Both stderr and stdout are flushed. // eprint prints a message to stderr. Both stderr and stdout are flushed.
pub fn eprint(s string) { pub fn eprint(s string) {
if s.str == 0 {
eprint('eprint(NIL)')
}
C.fflush(C.stdout) C.fflush(C.stdout)
C.fflush(C.stderr) C.fflush(C.stderr)
C.write(2, s.str, s.len) if s.str == 0 {
C.write(2, c'eprint(NIL)\n', 12)
} else {
C.write(2, s.str, s.len)
}
C.fflush(C.stderr) C.fflush(C.stderr)
} }
@ -143,36 +145,32 @@ pub fn println(s string) {
[unsafe] [unsafe]
pub fn malloc(n int) byteptr { pub fn malloc(n int) byteptr {
if n <= 0 { if n <= 0 {
panic('malloc(<=0)') panic('> V malloc(<=0)')
} }
$if vplayground ? {
if n > 10000 {
panic('allocating more than 10 KB is not allowed in the playground')
}
}
$if trace_malloc ? {
total_m += n
C.fprintf(C.stderr, c'v_malloc %d total %d\n', n, total_m)
// print_backtrace()
}
mut res := byteptr(0)
$if prealloc { $if prealloc {
// println('p') res = g_m2_ptr
res := g_m2_ptr
unsafe { unsafe {
g_m2_ptr += n g_m2_ptr += n
} }
nr_mallocs++ nr_mallocs++
return res
} $else { } $else {
ptr := unsafe {C.malloc(n)} res = unsafe { C.malloc(n) }
if ptr == 0 { if res == 0 {
panic('malloc($n) failed') panic('malloc($n) failed')
} }
return ptr
} }
/* return res
TODO
#ifdef VPLAY
if n > 10000 {
panic('allocating more than 10 KB is not allowed in the playground')
}
#endif
#ifdef DEBUG_ALLOC
total_m += n
println('\n\n\nmalloc($n) total=$total_m')
print_backtrace()
#endif
*/
} }
/* /*
@ -180,23 +178,38 @@ pub fn malloc(n int) byteptr {
fn malloc_size(b byteptr) int fn malloc_size(b byteptr) int
*/ */
// v_realloc resizes the memory block `b` with `n` bytes. // v_realloc resizes the memory block `b` with `n` bytes.
// The `b byteptr` must be a pointer to an existing memory block previously allocated with `malloc`, `v_calloc` or `vcalloc`. // The `b byteptr` must be a pointer to an existing memory block
// previously allocated with `malloc`, `v_calloc` or `vcalloc`.
[unsafe] [unsafe]
pub fn v_realloc(b byteptr, n int) byteptr { pub fn v_realloc(b byteptr, n int) byteptr {
mut new_ptr := byteptr(0)
$if prealloc { $if prealloc {
unsafe { unsafe {
new_ptr := malloc(n) new_ptr = malloc(n)
size := 0 // malloc_size(b) C.memcpy(new_ptr, b, n)
C.memcpy(new_ptr, b, size)
return new_ptr
} }
} $else { } $else {
ptr := unsafe {C.realloc(b, n)} $if debug_realloc ? {
if ptr == 0 { // NB: this is slower, but helps debugging memory problems.
panic('realloc($n) failed') // The main idea is to always force reallocating:
// 1) allocate a new memory block
// 2) copy the old to the new
// 3) fill the old with 0x57 (`W`)
// 4) free the old block
// => if there is still a pointer to the old block somewhere
// it will point to memory that is now filled with 0x57.
new_ptr = malloc(n)
C.memcpy(new_ptr, b, n)
C.memset(b, 0x57, n)
C.free(b)
} $else {
new_ptr = unsafe { C.realloc(b, n) }
if new_ptr == 0 {
panic('realloc($n) failed')
}
} }
return ptr
} }
return new_ptr
} }
// v_calloc dynamically allocates a zeroed `n` bytes block of memory on the heap. // v_calloc dynamically allocates a zeroed `n` bytes block of memory on the heap.