不安全代码

内存安全/不安全函数

默认情况下:

所有的V函数调用都是内存安全的,可信的,

所有的C函数调用都是内存不安全的,不可信的,

如果要把某个V函数定义为内存不安全的,要给函数加上unsafe注解,

如果要把C函数定义为内存安全的,可信的,要给函数加上trusted注解,

不管是V函数还是C函数,所有内存不安全的函数都要在unsafe代码块中调用,否则编译器会报错.

1. [unsafe] //注解V函数为不安全的函数,因为里面有手动的内存控制或指针运算等内存不安全操作
2. pub fn (a array) free() {
3. //if a.is_slice {
4. //return
5. //}
6. C.free(a.data)
7. }
1. // v/builtin/cfns.c.v
2. [trusted] //注解C函数为安全的,信任的函数
3. fn C.calloc(int, int) &byte

5. fn C.malloc(int) &byte

7. fn C.realloc(a &byte, b int) &byte

9. fn C.free(ptr voidptr)

11. [trusted]
12. fn C.exit(code int)

unsafe函数必须在unsafe代码块中调用

1. fn my_fn() {
2. unsafe {
3. //在这里才能调用不安全函数
4. }
5. //在unsafe代码块之外调用,编译器会警告
6. }

在不安全代码块中进行指针运算和多级指针,编译器啥都不管,自己掌控,就跟C一样

1. module main

3. fn main() {
4. unsafe {
5. v := 4
6. mut p := &v
7. // unsafe代码块中可以进行指针运算,编译器不负责检查
8. p++
9. p += 2
10. p = p - 1
11. println(p)
12. p = p + 1
13. println(p)
14. r := p++
15. println(r)
16. //多级指针
17. n := 100
18. pn := &n
19. ppn := &pn
20. mut pppn := &ppn
21. println(pppn)
22. }
23. }

不安全表达式

1. module main

3. fn main() {
4. mut q := &byte(10)
5. println(q)
6. unsafe {
7. q -= 2
8. q = q + 1
9. }
10. println(q)
11. //不安全表达式,返回指针运算后的结果
12. s := unsafe { q - 1 }
13. println(s)
14. unsafe {
15. q++
16. q++
17. q--
18. }
19. println(q)
20. }