不安全代码

内存安全/不安全函数

默认情况下:

所有的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
  4. fn C.malloc(int) &byte
  5. fn C.realloc(a &byte, b int) &byte
  6. fn C.free(ptr voidptr)
  7. [trusted]
  8. fn C.exit(code int)

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

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

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

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

不安全表达式

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