zworld-em/Source/zworld/CrashActor.cpp

127 lines
2.7 KiB
C++
Raw Normal View History

2025-05-17 18:56:46 +08:00
// Fill out your copyright notice in the Description page of Project Settings.
#include "CrashActor.h"
DEFINE_LOG_CATEGORY(LogCrash);
// Sets default values
ACrashActor::ACrashActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ACrashActor::BeginPlay()
{
Super::BeginPlay();
}
void TestCrash(int CrashFrame) {
auto FN = [=]() {
int* ptr = nullptr;
*ptr = CrashFrame + 6;
};
FN();
}
2025-05-30 19:06:39 +08:00
ETestCrashType CrashNameToEnum(const FString& CrashName) {
UEnum* CrashEnumPtr = nullptr;
if (!CrashEnumPtr)
{
CrashEnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("ETestCrashType"), true);
}
2025-05-17 18:56:46 +08:00
2025-05-30 19:06:39 +08:00
if (!CrashEnumPtr)
{
return ETestCrashType::NullPointer;
}
return static_cast<ETestCrashType>(CrashEnumPtr->GetValueByNameString(CrashName));
}
void CrashTest(FString CrashName) {
ETestCrashType Type = CrashNameToEnum(CrashName);
switch (Type)
{
case ETestCrashType::NullPointer:
{
volatile char* ptr = nullptr;
*ptr += 1;
}
break;
case ETestCrashType::ArrayOutOfBounds:
{
TArray<int32> emptyArray;
emptyArray[0] = 10;
}
break;
case ETestCrashType::BadFunctionPtr:
{
void(*funcPointer)() = nullptr;
funcPointer();
}
break;
case ETestCrashType::IllegalAccess:
{
int* addrPtr = reinterpret_cast<int*>(0x12345678);
*addrPtr = 10;
}
break;
case ETestCrashType::StackOverflow:
{
using CrashRecursiveFnType = void (*)(int counter);
static CrashRecursiveFnType CrashFn;
CrashFn = [](int counter)
{
volatile int data[1024]; // 每次递归分配额外栈空间加速溢出
UE_LOG(LogTemp, Warning, TEXT("Depth: %d"), counter);
CrashFn(data[0] + 1); // 无限递归
};
CrashFn(1);
}
break;
case ETestCrashType::CrashOOM:
{
// 持续分配内存直到崩溃
TArray<void*> MemoryBlocks;
while (true)
{
// 每次分配 100MB调整数值适配测试环境
void* Block = FMemory::Malloc(100 * 1024 * 1024);
if (!Block)
{
// 分配失败时主动崩溃或记录日志
UE_LOG(LogTemp, Fatal, TEXT("OOM崩溃触发"));
break;
}
MemoryBlocks.Add(Block);
}
}
break;
case ETestCrashType::Assert:
{
char* assertPtr = nullptr;
check(assertPtr != nullptr);
}
break;
case ETestCrashType::Ensure:
{
char* ensurePtr = nullptr;
ensure(ensurePtr != nullptr);
}
break;
default:
{
UE_LOG(LogTemp, Warning, TEXT("Uknown app termination type!"));
}
break;
}
}
2025-05-17 18:56:46 +08:00
// Called every frame
void ACrashActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
2025-05-30 19:06:39 +08:00
CrashFrame = 100;
2025-05-17 18:56:46 +08:00
if (Frame++ >= CrashFrame) {
2025-05-30 19:06:39 +08:00
UE_LOG(LogTemp, Error, TEXT("ACrashActor:BeforeCrash"));
CrashTest("CrashOOM");
//TestCrash(CrashFrame);
2025-05-17 18:56:46 +08:00
}
}