编程学习Bug记录

本文详细记录了C++编程过程中遇到的多种错误,包括编译器错误、模板使用、内存管理、构造函数问题、UE4开发中的Bug,如对象路径冲突、组件问题和事件绑定等,提供了相应的解决方法。
摘要由CSDN通过智能技术生成

C++学习Bug记录

Bug1——无法解析的外部命令

编译器报错
fatal error LNK1120: 5 个无法解析的外部命令
在博客上和《C++PrimerPlus》上找到了Bug原因

因创建类模板,模板不是函数,不能单独编译。模板必须与特定的模板实例化请求一起使用。不能将模板成员函数放在独立的实现文件中。

解决方法
在使用文件中包含Cpp文件、或者将所有模板信息放在一个头文件中,并在要使用这些模板的文件中包含该头文件。

Bug2——_Val 0xcdcdcdcdcdcdcdcd

编译器报错
_Val 0xcdcdcdcdcdcdcdcd <读取字符串字符时出错。> const char *

Bug原因

使用cout << 输出 const char*类型的数据时,遇到了一块未定义的内存。

	for (int j = 0; j < charStrArr.GetCapacity(); j++)		//这里charStrArr.GetCapacity()函数返回数组的最大容量,然而数组存储的元素数量远小于容量
		cout << charStrArr[j] << " ";

解决方法
将GetCapacity()函数更改为GetSize()函数

Bug3——delete_scalar

编译器报错
delete_scalar文件出现异常,delete(block)

Bug原因
使用了new分配空间,后delete时,内存可能已经被释放了,变成了野指针。

template <typename T>
void MyArray<T>::push_back(T elem)
{
	if (size >= capacity)		//数组还有内存
	{
		//数组已满
		this->resize(size + 1);
	}

	Elem[size++] = elem;	//插入到尾部 未重载elem,导致Elem元素与elem共用同一块内存,在elem元素调用析构函数时,Elem中的元素内存也随之释放,但是Elem指针仍然指针指向那块区域
}

Bug4——error C2436

编译器报错
error C2436: “hold”: 构造函数初设定项列表中的成员函数或嵌套类始值

Bug原因
在构造函数中使用列表初始化给嵌套类传递值。

template <typename T>
class nestTemplate
{
private:
	template <typename V>
	class hold;
	hold<T> h;

public:
	nestTemplate(T v) : hold(v) {}		//这里未注意用了嵌套类型名,应使用嵌套类成员对象

	template <typename U>
	void show(T a, U b) const;
};

Bug5——[Error] operator<<must take exactly one argument

编译器报错

[Error] 'std::ostream& VintagePort::operator<<(std::ostream&, const VintagePort&)' must take exactly one argument

Debug后
operator<<为二元运算符,若函数为成员函数,this会成为默认的第一个参数,所有参数列表只能为一个参数,即ostream& os,则调用形式为 p << cout;
所有重载<<运算符需要声明为友元函数,定义时不需要使用类作用域符。

	friend ostream& operator<<(ostream& os, const Port& p);	
	
	ostream& operator<<(ostream& os, const Port& p)
{
	os << p.GetBrand() << ", " << p.GetStyle() << ", " << p.GetBottles();
	return os;
}

UE4C++学习Bug记录

Bug1—— UObject() constructor called but it’s not the object that’s currently

being constructed with NewObject
编译器报错
UObject() constructor called but it’s not the object that’s currently
being constructed with NewObject. Maybe you are trying to construct it
on the stack, which is not supported.

错误原因:
程序在创建派生类对象时,首先创建基类对象。即派生类在调用构造函数之前,应调用基类的构造函数。

错误代码

AAM_Hero::AAM_Hero() 
{
	Super::AHeroCharacter();	//在派生类构造函数中,调用了基类的构造函数
	PossessWeapon = false;
}

Debug后
C++使用成员初始化列表完成这份工作

AAM_Hero::AAM_Hero() : AHeroCharacter()
{
	PossessWeapon = false;
}

Bug2——Objects have the same fully qualified name but different paths.

编译器报错

Objects have the same fully qualified name but different paths. New
Object: AM_Hero /Engine/Transient.Default__AM_Hero Existing Object:
HOTRELOADED_AM_Hero_1 /Engine/Transient.Default__AM_Hero

Debug后
构造函数调用多次,使用初始化列表调用基类构造函数。

Bug3——error C2027: 使用了未定义类型“UArrowComponent”

编译器报错

error C2027: 使用了未定义类型“UArrowComponent”

Debug后
未包含组件头文件

Bug4——EXCEPTION_ACCESS_VIOLATION reading address 0x00000000000001c0

编译器报错

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000000000001c0

意思应该是遇到了空指针。

SetLifeSpan(1.2f);

Debug后
SetLifeSpan()函数不能在构造函数中调用,可以在Begin后调用。

这里是源码实现

void AActor::SetLifeSpan( float InLifespan )
{
	// Store the new value
	InitialLifeSpan = InLifespan;
	// Initialize a timer for the actors lifespan if there is one. Otherwise clear any existing timer
	if ((GetLocalRole() == ROLE_Authority || GetTearOff()) && !IsPendingKill())
	{
		if( InLifespan > 0.0f)
		{
			GetWorldTimerManager().SetTimer( TimerHandle_LifeSpanExpired, this, &AActor::LifeSpanExpired, InLifespan );
		}
		else
		{
			GetWorldTimerManager().ClearTimer( TimerHandle_LifeSpanExpired );		
		}
	}
}

Bug5—— Error: BlueprintReadOnly should not be used on private members

编译器报错

LogCompile: Error: BlueprintReadOnly should not be used on private members

DeBug后
在属性说明符中添加元数据说明符meta = (AllowPrivateAccess = “true”)或者修改private

private:
	//武器射击输入阈值
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "AdventureMode-Hero", meta = (AllowPrivateAccess = "true"))
	float ThresholdValue;

Bug6——error LNK2019: 无法解析的外部符号

编译器报错

error LNK2019: 无法解析的外部符号 "__declspec(dllimport) private: static class UClass * __cdecl UWidgetComponent::GetPrivateStaticClass(void)"

Debug后

未在工程文件Bulid.cs中添加依赖

// Fill out your copyright notice in the Description page of Project Settings.
using UnrealBuildTool;
public class YourProject : ModuleRules
{
    public YourProject(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(new string[] { 
            "Core", 
            "CoreUObject", 
            "Engine", 
            "InputCore", 
            "UMG"		//新添加的
            }
        );
        PrivateDependencyModuleNames.AddRange(new string[] {  });
		//这里也许注意
        // Uncomment if you are using Slate UI
        PrivateDependencyModuleNames.AddRange(new string[] { 
            "Slate", 
            "SlateCore" 
            }
        );
        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");

        // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
    }
}

Bug7——error C2923: “TSubclassOf”: “AProjectile” 不是参数 “TClass” 的有效 模板 类型参数

编译器报错

error C2990: “TSubclassOf”: 非类 模板 已经声明为类 模板
error C2923: "TSubclassOf": "AProjectile" 不是参数 "TClass" 的有效 模板 类型参数

Debug后

	//声明形式
	TSubclassOf<class AProjectile> ProjectileToSpawn;

Bug8——UE_LOG

注意UE_LOG中文本TEXT的变量类型需要对应,float类型的变量对于%f,整型对应%d,字符串对应%s。

	UE_LOG(LogTemp, Warning, TEXT("PC Get EXP = %f"), EXPValue);

Bug9——error LNK2001: 无法解析的外部符号 "UBTTask_GhoulAttack::ExecuteTask

未在工程文件中添加模块依赖,在Build.cs文件下添加AIModule,GamePlayTasks模块

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG", "AIModule", "GamePlayTasks"});

Bug10——SetMasterPoseComponent失效

在构造函数中使用SetMasterPoseComponent(),结果编辑器和游戏中均为奏效。

Quiver->SetMasterPoseComponent(GetMesh());

解决办法
重写PostInitializeComponents()方法,并将逻辑写在此中,而不是构造函数中。

	virtual void PostInitializeComponents() override;

Bug11——Actor重叠事件绑定失败

在构造函数中使用OnActorBeginOverlap和OnComponentBeginOverlap绑定重叠事件,也设置了生成重叠事件,在编辑器中使用蓝图发现确实生成了重叠事件,但是并没有调用绑定的自定义重叠事件,最后选择了在蓝图中调用C++函数。

OnActorBeginOverlap.AddDynamic(this, &AArrowProjectile::OnArrowBeginOverlap);

void AArrowProjectile::OnArrowBeginOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
	UE_LOG(LogTemp, Warning, TEXT("ArrowOverlap"));
	AHeroCharacter* Hero = Cast<AHeroCharacter>(OtherActor);
	if(Hero)
	{
		
		Hero->CalculateHealth(-ProjectileDamage);
		this->Destroy();
	}
}

Bug12——骨骼插槽绑定

我在构造函数里使用了SetupAttachment()函数,函数参数需传入一个USceneComponent组件以及插槽名FName,FName默认为Name_None。

	void SetupAttachment(USceneComponent* InParent, FName InSocketName = NAME_None);
	//我的使用方法
	ParticleSystem->SetupAttachment(GetMesh(), FName("Middle_r"));

有时这种绑定插槽会没有效果,这里建议使用TEXT(“插槽名”)作为参数。

	LeftCapsuleCollision->SetupAttachment(GetMesh(), TEXT("MiddleFinger1_L"));

Bug13——Character的声明隐藏了类成员

编辑器报错

	AHeroCharacter* Character = Cast<AHeroCharacter>(GetPawn());

原因
在UE内部已经定义了Character的成员,这时又定义了Character的局部变量,产生了冲突。

Bug14——OnComponentBeginOverlap事件绑定未生效

//创建一个球形碰撞体组件
SphereCollision = CreateDefaultSubobject<USphereComponent>(TEXT("SphereCollision"));
//绑定重叠事件
SphereCollision->OnComponentBeginOverlap.AddDynamic(this, &ASphereProjectile::OnBeginOverlap);

这个时候在编辑器里发现绑定并未生效,我在构造函数里将组件绑定至根组件后,解决了问题。

//创建一个球形碰撞体组件
SphereCollision = CreateDefaultSubobject<USphereComponent>(TEXT("SphereCollision"));
SphereCollision->SetupAttachment(RootComponent);
//绑定重叠事件
SphereCollision->OnComponentBeginOverlap.AddDynamic(this, &ASphereProjectile::OnBeginOverlap);

Bug15——BlueprintImplementableEvents in Interfaces must not be declared ‘virtual’

class TWINSTICKSHOOTER_API IITraceable
{
	GENERATED_BODY()
public:
	//这里使用了Virtual
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ITraceable")
		virtual bool TraceBegin();
}

解决方法

UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ITraceable")
	bool TraceBegin();
virtual bool TraceBegin_Implementation();

bool IITraceable::TraceBegin_Implementation()
{
	return false;
}

这样既可以在蓝图中、也可以在子类当中重写接口函数

Bug16——中文输出乱码

Bug17——Fatal error: [Line: 475] Pure virtual function being called

添加自定义游戏实例后,出现引擎崩溃的问题,在自定义游戏实例中重写这些函数.

virtual void Init() override;
virtual void Shutdown() override;
virtual void StartGameInstance() override;
  • 26
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值