zoukankan      html  css  js  c++  java
  • unreal3之FName及潜在bug

    FName是unreal3里对字符串高效处理的一种机制

    基本原理就是把字符串hash存起来,然后每个字符串就只需要用一个数组索引值来表示了

    FName的属性:

    NAME_INDEX Index;

    INT Number;

    Index就是数组索引,Number是一种特殊用途:系统在生成对象时通常会规律自动起名,如Object_12、Object_13、Object_14等等,若每一个都单独保存就很浪费,FName会把它末尾的数字拆开,只对前半节做hash保存,这样三个名字得到的Index值都一样了,而不一样的数字部分则存在Number里。

    FName的实例属性也就这两个,其它都是静态成员了,就是数组和hash表:

    /** Table of all names. This is a NoInit because we may need to use it before the constructor is called due to random static variable initialization order */
        static TArrayNoInit<FNameEntry*>    Names;
        /** Name hash.                                                */
        static FNameEntry*                    NameHash[ FNameDefs::NameHashBucketCount ];

    其中Names就是所有FName按先来后到顺序存放的数组,当要从一个FName获取其FString时,就是通过Names[Index]->AnsiName来访问了

    而NameHash则是用来快速查找的hash表,其索引就是各字符串的hash值。

    然而这个hash值的计算是忽略大小写的,这就导致一个大问题:

    FName居然是不区分大小的!

    就算UnrealEngine内部自己约定,所有名字变量都不区分大小写,也仍然有问题,因为,C++语言本身是区分大小写的!

    我就碰到过一个这样的bug:

    当重新编译脚本并生成C++头文件时,FURL里有一个字段Host,在脚本定义时明明是大写,可是一生成C++代码就成了小写,按理说这是相当基础的内部类,我根本就不可能改到它,为什么它会自己变样呢?如果我尝试把它名字改成Host2之类的,它就不会变小写了。

    经过一连串的跟踪,终于在调试器的帮助下找到了原因:因为在解析uc文件里的每一句变量声明时,都会用一个FName来保存读到的变量名,而如果这串字符之前已经有遇到过,那么无论其大小写是否一样,都会认为是同一个值并使用之前已经存储的版本,而此次的真实值就被抛弃了。恰好我在INI文件里定义了一个host=XXXX的属性对,由于加载INI在前,解析脚本类在后,所以当解析到FURL结构里的Host字段时,发现FName::Names里已经有了一个小写的host项,就直接把它当作变量名使用了!然而C++编译器可是区分大小写的,原来代码里那么使用Host的地方,在小写的新版头文件下,肯定编译出错。

    解决的办法,当然只能是去修改INI里的Key了,然而这真的是一个非常隐蔽的BUG啊,哪天又一不小心重名了,分分钟跳坑。。。

  • 相关阅读:
    奇怪吸引子---Bouali
    奇怪吸引子---Arneodo
    奇怪吸引子---AnishchenkoAstakhov
    奇怪吸引子---Aizawa
    混沌图像---三翅鹰
    混沌图像---马丁迭代【密集恐惧症患者慎入】
    混沌图像---埃农的猫头鹰
    MySQL存储过程 事务transaction
    OBS直播抖音。。。
    [译][python]ImportError:attempted relative import with no known parent package
  • 原文地址:https://www.cnblogs.com/wellbye/p/5391028.html
Copyright © 2011-2022 走看看