关于PB里 reference value readonly 3 种参数引用类型
本题目从一小段代码开始:
//====================================================================
// Function: uo_tabpage_xml.of_print_xml_nodes
//--------------------------------------------------------------------
// 描述:
//--------------------------------------------------------------------
// 参数:
// readonly long al_count
// readonly uo_xml_node ao_node[]
//--------------------------------------------------------------------
// 返回: integer
//--------------------------------------------------------------------
// 作者: 大自在(QQ781770213) 日期: 2020/07/15 14:29:42
//--------------------------------------------------------------------
// CopyRight(c)
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================
long i,ll_count
uo_xml_node nodes[]
for i = 1 to al_count
ll_count = ao_node[i].Get(ref nodes[])
lb_1.additem("a")
of_print_xml_nodes(ll_count,nodes[])
next
return 1
这个题目,就从这段代码开始。这段代码,它就是一个递归,里面用到了 我写的一个对象 uo_xml_node。开始的时候,参数引用类型使用了 value,程序一运行,就崩溃,后来把参数类型改为 readonly ,就一切正常了。于是对以前没多注意的参数引用类型做了一些思考,想清楚了个中原因。
由于PB是由C++开发的,站在这个角度,我们先来看看PB的参数是个什么东东。先看一个数据结构:
struct ob_data
{
OB_VALUE val;
OB_INFO_FLAGS info; // Data node info flags
OB_CLASS_ID type; // Data Type
};
这个 ob_data,就是PB的参数,PB的每一个变量,int ,long,window.... 所有类型,其实在PBVM里,都是这样的一个 ob_data。它的 type 指明了是一个什么类型,比如 1 是 int,2是long,6是string,大于22的基本上就是对象。
具体到 OB_VALUE这个,它是一个union,可以是指针,可以是普通变量。info这个值,它有各种指示,非常复杂,暂时不管它。
假如有一个参数 ob_data myarg;
1、reference引用:
它实际上是这样的:
ob_data value;
myarg.info= 我是一个引用
myarg.ob_value = &myarg;
明白了吧,它是一个结构,再套一个指针,实际使用时,指的是ob_value里的指针。
2、valu引用:
copy myarg myargClonc;
也就是原封不动地将原结构,复制了一份,里面的内容不动,然后修改里面的 myargClone.info 后,传递给程序。
3、readonly引用:
这个它就简单了,直接传的是 &myarg;
说到这里,咱们回到今天的主题上。为什么我直接用 value 传参数会崩溃呢?
原因是:每一个uo_xml_node的内部,我对应了一个C++对象的指针,在对象 destroy 时,做了 delete 指针操作。所以 value 引用时,因为clone了另一个结构,2个结构里面的指针一样,指向同一个C++对象,被 delete 了2次,所以程序出问题了。而readonly只是传 &myarg ,不会导致我内部的C++对象被2次 delete。
问题想明白了。吸取一个经验教训:凡我在 pbjson.dll 里写的这些对象,作为参数引用时,都要用 readonly 方式,不要使用value方式。
另外说一点,是不是用 readonly 就省事安全呢?其实也未必 。因为PB里面,它每一个线程都有自己独立 的堆管理。它的变量是不允许跨堆 使用的,否则程序会崩溃。 这也是PB里为什么各线程之间的变量不能互相访问的根本 原因。跨线程传参数,是必须要用 value 的,它会由各自线程在自己堆上建立新的变量。甚至有些同一线程内部因为变量生命周期的原因,也需要用 value方式,否则 用 readonly 方式得到的 &myarg 指针,有可能是无效的指针,导致程序出问题。
当然,同一线程内,内部不是把对象和指针绑定的情况下,传 readonly和 value,没多大区别,copy 一个 ob_data 的性能差别,可以忽略不计。
本文地址:https://blog.csdn.net/lxbin2003/article/details/107360085