关于PB里 reference value readonly 3 种参数引用类型

2022-08-02,,,,

本题目从一小段代码开始:

//====================================================================
// 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

《关于PB里 reference value readonly 3 种参数引用类型.doc》

下载本文的Word格式文档,以方便收藏与打印。