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啊,哪天又一不小心重名了,分分钟跳坑。。。
unreal3之FName及潜在bug的更多相关文章
- Session 潜在bug防范
注意: Session的使用一定要及时的清理,因为它是“全局”的(包括其生命周期),所以在使用Session保存状态时,不用时要及时的NULL掉,小心潜在的Bug.
- Java-idea-FindBugs字节码级别潜在bug查看
一.概述 静态分析工具承诺无需开发人员费劲就能找出代码中已有的缺陷. FindBugs 不注重样式或者格式,它试图只寻找真正的缺陷或者潜在的性能问题. FindBugs 是一个静态分析工具,它检查类或 ...
- Java-idea-PMD源文件级别潜在bug查看
一.概述 PMD(Project Manager Design)是一种开源分析Java代码错误的工具.与其他分析工具不同的是,PMD通过静态分析获知代码错误.也就是说,在不运行Java程序的情况下报告 ...
- 检测代码潜在bug和质量之SonarQube
参数使用 项目分析参数可以在多个地方设置,继承关系如下: 全局分析参数,通过Web UI设置,作用于所有项目(配置–>通用–>通用中设置) 项目分析参数,通过WebUI设置,覆盖全局参数( ...
- 添加PMD插件扫描潜在的bug
上一节使用checkstyle来规范你的项目主要解决了代码编码规范问题,比如缩进换行等.这次继续代码健康工具类PMD. 什么是PMD PMD真的不像checkstyle这样的东西所见即所得啊,去官网找 ...
- Erlang 程序引发共享内存 bug 的一个例子
虽然 Erlang 的广告说得非常好,functional.share-nothing.消息传递,blah blah 的,好像用 Erlang 写并发程序就高枕无忧了,但是由于 Erlang 信奉高度 ...
- 实际例子描述和分析“猎豹抢票跨站推荐功能有票刷不到”的疑似bug
前言 快过年了,又到了一年抢票时.今年douba和douma计划要带着doudou回姥姥家.昨天在家用抢票软件居然发现了一个bug,那就是在猎豹抢票中跨站推荐的车票几天里一直是没有,但是在12306手 ...
- 关于C/C++语言的部分BUG
目录 scanf格式匹配引发的错误 局部变量被释放引发的bug 数组写入超出索引维度 指针的指针引发的思考 未定义赋值的变量引发的bug 题外话 scanf格式匹配引发的错误 运行如下程序时,出现 ...
- UVa 658 - It's not a Bug, it's a Feature!(Dijkstra + 隐式图搜索)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
随机推荐
- IOCP之客户端及消息传递
上篇说到IOCP的精简实现,这篇来讲IOCP客户端和消息传递 在ConnectEx代码之前,CreateIoCompletionPort的第三个参数,把socket句柄+0x01000000作为传递 ...
- FCKeditor 2.6.4.1 初始化值不能显示中文问题
最近在学习PHP加入FCKeditor 在线编辑器,发现在初始化Value赋值时,英文可以显示出来,中文怎么都显示不出来,连乱码都不显示. 经过漫长的探索,终于找到原因了! 在fckeditor目录下 ...
- 主从Reactor多线程模型
Reactor 单线程--多线程--主从多线程
- Array,ArrayList、List<T>、HashSet<T>、LinkedList<T>与Dictionary<K,V>
Array: 数组在C#中最早出现的.在内存中是连续存储的,所以它的索引速度非常快,而且赋值与修改元素也很简单. 但是数组存在一些不足的地方.在数组的两个数据间插入数据是很麻烦的,而且在声明数组的时候 ...
- delphi 调用c#dll
public interface iProduct { string Buy(); } [ClassInterface(ClassInterfaceType.None)] public class P ...
- nginx/Windows-1.9.3启动脚本
启动nginx.bat @echo off D: cd D:\Program Files\nginx-1.9.3 tasklist | findstr /i "nginx.exe" ...
- testng 控制case运行顺序
Testing.xml 文档结构: <test name="xxxx" preserve-order="false"> <!-- 参数定义的方 ...
- linux 查询目录下包含关键字的所有文件
linux查找目录下的所有文件中是否含有某个字符串 查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri "IBM" 查找目录下的所有文件中是否含有 ...
- LINUX下查看负载
1,查看磁盘 df -h 2,查看内存大小 free free [-m|g]按MB,GB显示内存 vmstat 3,查看cpu cat /proc/cpuinfo 只看cpu数量grep " ...
- Eclipse JSP/Servlet 环境搭建
Eclipse JSP/Servlet 环境搭建 本文假定你已安装了 JDK 环境,如未安装,可参阅 Java 开发环境配置. 我们可以使用 Eclipse 来搭建 JSP 开发环境,首先我们分别下载 ...