Tencent/puerts

[Unity] Bug: 使用NativeAOT编译后,js获取空的c#字符串时会直接崩进程

Closed this issue · 20 comments

前置阅读 | Pre-reading

Puer的版本 | Puer Version

2.0.4

Unity的版本 | Unity Version

dotnet 8

发生在哪个平台 | Platform

Other

错误信息 | Error Message

控制台没有输出,游戏直接崩溃

问题重现 | Bug reproduce

使用NativeAOT编译程序,在js调用返回空字符串的c#方法,比如在自定义模块加载器的ReadFile方法中返回""。

可以加个用例重现吗?我们的UT是在dotnet下跑的,参考这个,c95456f

可以加个用例重现吗?我们的UT是在dotnet下跑的,参考这个,c95456f

图片
这个测试应该就可以,我一开始也是发现导入不存在的模块会崩,后面发现是因为loader.ReadFile在找不到模块的时候返回了空字符串,NativeAOT编译后,返回空字符串的C#方法和属性在js调用就崩。

可以加个用例重现吗?我们的UT是在dotnet下跑的,参考这个,c95456f

图片 这个测试应该就可以,我一开始也是发现导入不存在的模块会崩,后面发现是因为loader.ReadFile在找不到模块的时候返回了空字符串,NativeAOT编译后,返回空字符串的C#方法和属性在js调用就崩。

每个commit UT用例都会执行,这些用例都没导致崩溃。

可以加个用例重现吗?我们的UT是在dotnet下跑的,参考这个,c95456f

图片 这个测试应该就可以,我一开始也是发现导入不存在的模块会崩,后面发现是因为loader.ReadFile在找不到模块的时候返回了空字符串,NativeAOT编译后,返回空字符串的C#方法和属性在js调用就崩。

每个commit UT用例都会执行,这些用例都没导致崩溃。

az,UT有开启NativeAOT?

应该没开NativeAOT,同样的代码,只有NativeAOT才会崩溃吗?崩溃的栈发下看看?

应该没开NativeAOT,同样的代码,只有NativeAOT才会崩溃吗?崩溃的栈发下看看?

对,只有NativeAOT会崩溃,而且没有栈输出,先是卡死一两秒,然后进程直接结束,控制台也没有输出

我们用dotnet test xxx.csproj来执行测试,你看看又没什么参数启动NativeAOT
https://github.com/Tencent/puerts/blob/master/unity/cli/test.mts#L117

我们用dotnet test xxx.csproj来执行测试,你看看又没什么参数启动NativeAOT https://github.com/Tencent/puerts/blob/master/unity/cli/test.mts#L117

我没找到(

要不你附带一个能重现的最小工程给我?

要不你附带一个能重现的最小工程给我?

抱歉让大佬久等了
压缩文件 (1).zip
关闭aot:
图片
开启aot:
图片

我jit方式在linux下也能重现,解决了我重现的场景,你试试看看。

原因:
Exist或者Resole成功,会去读取文件内容,如果文件内容返回undefined,该代码转成字符串后编译,v8会abort,报:

# Fatal error in , line 0
# unreachable code
#
#
#

我jit方式在linux下也能重现,解决了我重现的场景,你试试看看。

原因: Exist或者Resole成功,会去读取文件内容,如果文件内容返回undefined,该代码转成字符串后编译,v8会abort,报:

# Fatal error in , line 0
# unreachable code
#
#
#

呃,但我测试是可以在ReadFile方法里返回null的,现在也是这样临时解决的,返回空字符串的c#方法都改成了返回null

我jit方式在linux下也能重现,解决了我重现的场景,你试试看看。

原因: Exist或者Resole成功,会去读取文件内容,如果文件内容返回undefined,该代码转成字符串后编译,v8会abort,报:

# Fatal error in , line 0
# unreachable code
#
#
#

而且不只是模块读取不能返回空字符串,是所有C#方法与属性都不能返回空字符串

我jit方式在linux下也能重现,解决了我重现的场景,你试试看看。

原因: Exist或者Resole成功,会去读取文件内容,如果文件内容返回undefined,该代码转成字符串后编译,v8会abort,报:

# Fatal error in , line 0
# unreachable code
#
#
#

测试了,和之前一样,AOT后C#方法与属性返回空字符串会直接崩,问题没有解决

可能对于"",Encoding.UTF8.GetBytes会有什么特别

根据你的现象来看,感觉当字符串为""时,返回的字符串是非空结尾的,于是传过去后一直拷贝,于是卡在那一会儿访问到非法内存崩溃。

根据你的现象来看,感觉当字符串为""时,返回的字符串是非空结尾的,于是传过去后一直拷贝,于是卡在那一会儿访问到非法内存崩溃。

应该怎么检查呢?我自己调用Encoding.UTF8.GetBytes处理空字符串,jit与aot都是返回空缓冲区,好奇怪emmm

更新下吧,我这里ok了

更新下吧,我这里ok了

谢谢大佬!我这里测试也没问题了