-
Notifications
You must be signed in to change notification settings - Fork 179
Expand file tree
/
Copy pathDebug.carp
More file actions
69 lines (58 loc) · 2.62 KB
/
Debug.carp
File metadata and controls
69 lines (58 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
(system-include "carp_debug.h")
(doc Debug "is a module that provides functions and commands to debug faulty
programs and functions.")
(defmodule Debug
(doc sanitize-addresses "instructs the compiler to sanitize addresses.
This might not work on all compilers, but reasonably new versions of GCC and Clang are supported.
On Windows, this is disabled by default due to runtime library issues.")
(defndynamic sanitize-addresses []
(if windows-target?
(macro-log "Warning: AddressSanitizer is disabled on Windows (runtime library not available)")
(add-cflag "-fsanitize=address -Wno-macro-redefined")))
(doc check-allocations "will check the allocations made by the program
immediately, raising a `SIGABRT` if it fails.")
(defndynamic check-allocations []
(add-cflag "-DCHECK_ALLOCATIONS"))
(register memory-balance (Fn [] Long))
(register reset-memory-balance! (Fn [] ()))
(register log-memory-balance! (Fn [Bool] ()))
(doc memory-logged "logs all calls to memory allocation within the form. Requires the flag `--log-memory` to be passed during compilation.")
(defmacro memory-logged [form]
`(do
(Debug.log-memory-balance! true)
%form
(Debug.log-memory-balance! false)))
(doc assert-balanced "raises an error if the memory balance (number of `alloc`s - number of `free`s) isn't `0`. Requires the flag `--log-memory` to be passed durng compilation.")
(defmacro assert-balanced [form]
`(let [balance (Debug.memory-balance)]
(do
(let [] %form)
(unless (= balance (Debug.memory-balance))
(do
(IO.println &(fmt "Invalid memory balance: %d" (Debug.memory-balance)))
(ignore (System.exit 1)))))))
(doc trace "prints the value of an expression to `stdout`, then returns its value.")
(defmacro trace [x]
(let [sym (gensym)]
`(let-do [%sym %x]
; we use eval here to ensure we resolve the symbol before putting it
; into file, line, and column
(IO.println
(ref
(fmt "%s:%d:%d: %s"
%(eval `(file %x))
%(eval `(line %x))
%(eval `(column %x))
&(str %sym))))
%sym)
)
)
(doc leak-array "leaks some memory. This function is useful for testing tools that detect leaks.")
(register leak-array (Fn [a] ()) "Debug_leak_MINUS_array")
)
;; Crash the program with an error message unless the expression evaluates to 'true'.
(defmacro assert [expr]
`(unless (= true %expr)
(do
(println* (fmt "Assertion '%s' failed at line %d, column %d in file %s" %(str expr) %(line) %(column) %(file)))
(System.abort))))