zworld-em/Source/zworld/CrashActor.cpp
2025-05-30 19:06:39 +08:00

127 lines
2.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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();
}
ETestCrashType CrashNameToEnum(const FString& CrashName) {
UEnum* CrashEnumPtr = nullptr;
if (!CrashEnumPtr)
{
CrashEnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("ETestCrashType"), true);
}
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;
}
}
// Called every frame
void ACrashActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
CrashFrame = 100;
if (Frame++ >= CrashFrame) {
UE_LOG(LogTemp, Error, TEXT("ACrashActor:BeforeCrash"));
CrashTest("CrashOOM");
//TestCrash(CrashFrame);
}
}