UE4 内存写坏导致异常崩溃问题记录
1. 问题表现
经常出现进程崩溃,崩溃堆栈较为底层

原因基本上都是 read write memory 时触发了异常,盘查后初步怀疑是内存写坏了。
2. 排查期
UE 支持各种内存分配器:
- TBB
- Ansi
- Jemalloc
- Stomp
还有自带的内存分配器: - Binned
- Binned2
- Binned3
可以参考文章 UE 中的内存分配器。
其中 Stomp 是引擎提供的排查内存写坏的工具之一,通过增加参数-stompmalloc可以让 UE 默认采用该内存分配器,启用了之后崩溃的第一现场就是内存写坏的代码地址。
通过排查发现崩溃原因是遍历迭代器时删除元素后没有及时 continue,大致示例如下:
for(TArray<Actor*>::TIterator Iter(Actors); Iter; ++ Iter)
{
if (xxx)
{
Iter.RemoveCurrent(); //没有 continue
}
if (xxx)
{
Iter.RemoveCurrent();//没有 continue
}
}
当数组元素只剩一个时,如果触发了两次 RemoveCurrent,就会导致写到数组之外的内存空间,RemoveCurrent 的机制会把后面的数组元素迁移到删除的位置上,保证数据连贯。同时 RemoveCurrent 完毕后会自动把迭代器的下标前移一位。

3. Stomp 原理
3.1 内存覆盖
Stomp 其主要的功能是在写坏内存时可以马上捕获到第一现场。内存写坏了通常指程序在操作内存时写入了非法的数据或超出了内存分配的范围,导致程序出现错误或崩溃。这种情况通常被称为越界访问或非法访问内存。
大部分情况下有内存池的技术,且操作系统分配内存往往会向上按页对其分配,所以一时的内存越界读写有可能不会马上出现问题。而 Stomp 是在内存越界时就对其抛出异常。
3.2 实现原理
开启 Stomp 之后,内存分配基本上由 FMallocStomp::Malloc 和 FMallocStomp::Free 接管。
void* FMallocStomp::Malloc(SIZE_T Size, uint32 Alignment)
void FMallocStomp::Free(void* InPtr)
要做到写坏内存后能直接触发异常,需要在内存分配上做手脚,这里主要用到了两点:
- 操作系统支持的 Pagefault 和 Page 权限控制
- 哨兵机制
Stomp 在给用户分配内存的时候会额外分配 2 个 Page 出来,分别在返回给用户的指针地址空间前后。当用户超出分配给他的内存上读写时,就会触发异常。其分配内存的流程大致如下:

这里有个问题是 FAllocationData 只有 32 个字节,但是其分配了一个 Page 给其使用,这里主要是由于分配内存都需要对齐 Page。到此内存分配完毕,接下来有 2 种情况:
- 从 Page2 写数据一直写到 Page3,由于 Page3 被标记为不可读不可写,因此一旦出现越界,就会直接抛出异常
- 从 Page1 写数据一直写到 Page0,由于 Page0 末端分配了一个 FAllocationData,因此一旦越界,哨兵值会被覆盖,当释放内存时
FMallocStomp::Free就会对内存块的 FAllocationData 进行检查,一旦哨兵比对异常就抛出异常

UE4 内存写坏导致异常崩溃问题记录的更多相关文章
- 内存写越界导致破环堆结构引起的崩溃问题定位经验[如报错malloc(): memory corruption或free(): invalid next size]
前段时间开发的一个后端C模块上线后,线上出core,初始时,因为訪问压力不大,所以崩溃是上线3天左右出现的.当时用gdb跟进调用堆栈并检查源代码,发现出core位置的代码沒有啥问题.因为当时开发任务较 ...
- 疑似CPU或者内存故障导致进程崩溃
我们有一个服务跑在微软云的所有宿主机上.最近发现某一台机器上该服务进程持续崩溃.崩溃原因是访问了一个无效指针,对应的代码如下 serviceListIniBuffer.AppendF("Se ...
- IIS进程池异常崩溃,导致网站 service unavailable,原因排查与记录。
昨晚十点钟的样子,网站崩溃,开始 service unavailable,最近开始业务高峰,心里一惊,麻痹肯定进程池又异常崩溃了.又碰到什么问题?上次是因为一个异步线程的问题,导致了进程池直接崩溃,后 ...
- ArcGIS for Android 10.1.1API 中文标注导致程序异常崩溃问题
1.前言 问题:在部分Android机型中使用ArcGIS for Android 10.1.1 API 中文标注导致程序异常崩溃. 说明:手里有两台机器一台是Nexus4,原生系统,版本4.4.4, ...
- WPF 线程中异常导致程序崩溃
一般我们WPF中都加全局捕获,避免出现异常导致崩溃. Application.Current.DispatcherUnhandledException += Current_DispatcherUnh ...
- 修复UE4编辑器,ClearLog操作导致的崩溃
UE4 4.24.3版本,编辑器Output Log窗口中,右键--Clear Log操作很大概率会导致编辑器奔溃:解决办法: 相关文件: Engine\Source\Developer\Output ...
- Node出错导致运行崩溃的解决方案
许多人都有这样一种映像,NodeJS比较快: 但是因为其是单线程,所以它不稳定,有点不安全,不适合处理复杂业务: 它比较适合对并发要求比较高,而且简单的业务场景. 在Express的作者的TJ Hol ...
- 给虚拟机添加新硬盘并分区,fdisk查看分区,分区,重新读取分区表信息partprobe,格式化,挂载,查看分区挂载信息,自动挂载文件/etc/fstab,/etc/fstab文件错误导致重启崩溃后的修复
1.虚拟机关机断电 2.添加硬盘 2.开机 3.fdisk -l查看刚才新添加的硬盘 [root@localhost ~]# fdisk -l 磁盘 /dev/sda:21.5 GB, 2147483 ...
- 程序异常崩溃后用windbg辅助调试解决的经验 以及 堆栈问题调试经验
1,程序异常崩溃后用windbg辅助调试解决的经验 状况:我的程序调用别人的库做 文件写入工作. 在这一过程中出现异常,程序崩溃. 经反复检查,认为自己的程序没有错,但无法判断在别人库里哪里有错. ...
- Notepad++ 异常崩溃 未保存的new *文件列表没了怎么办?
今天就遇到这种问题了,把之前写的临时代码拷贝到Notepad++,不知道啥时候脑袋一抽风强迫症犯了就把所有临时代码给未保存关闭了,然后懊恼不已,百度了一下解决办法,一下就搜到了. Notepad++是 ...
随机推荐
- MySql数据库读取字段错误问题
一个小小的BUG,断断续续搞了一个月才搞定,使用MySql的时候使用mysql_fetch_fields()获取的字段始终始终是错误的,因为是修改别人的代码,一直找不到问题,Debug了无数次还是搞不 ...
- 使用python制作nRF52832升级包和合成烧录文件的经验(nRF52832 DFU经验分享)
使用python制作nRF52832升级包和合成烧录文件,青风开发板的作者已经说得很明白,不过作者使用的python是2.7的,已经很落后了.目前python已经更新到3.10.4了.所以我换了台电脑 ...
- springboot项目导出excel实现
参见:https://blog.csdn.net/duli_0105/article/details/102809936
- springboot中redis使用和工具
application.properties #Redis相关配置 spring.data.redis.host=localhost #端口 spring.data.redis.port=6379 # ...
- Tensorflow learning notebook
How does tensorflow work 原著blog https://jacobbuckman.com/#posts
- Python第十章实验报告
一.实验对象:<零基础学Python>6道实例和2道实战 二.实验环境:IDLE Shell 3.9.7 三.实验目的:学习如何在Python中进行文件和目录的相关操作 四.实验过程: 实 ...
- linux驱动设备分类
1. linux驱动设备分类 1.1 字符设备 -c 1.没有文件系统 2.应用程序和驱动程序之间进行数据交互时,数据是以"字节"进行数据交换,并且是按照固定的顺序传输的,数据是实 ...
- archlinux 源配置 桌面美化 终端美化 常用软件 grub配置
简介 本文讲对archlinux进行一些基础系统的配置.常用安装的安装,美化进行配置,先看一下美化后的效果吧 配置pacman和使用AUR(archlinuxcn源) archlinux采用滚动更新的 ...
- gRPC之.Net6中的客户端和服务端共用proto协议文件
1.说明 在上一篇文章gRPC之.Net6中的初步使用介绍中,我们简单的介绍了gRPC在服务端.客户端以及Web项目中的使用. 有一个问题,不知道大家发现没有,就是不管在服务端项目还是客户端项目中,我 ...
- 《程序员的自我修养》学习笔记——不一样的hello world【第四弹】
不一样的hello world Linux 的系统调用 通过glibc提供的库函数 glibc 是 Linux 下使用的开源的标准 C 库,它是 GNU 发布的 libc 库,即运行时库.glibc ...