Hello, everyone.
I’m in Unity 2021.3.23f1, Windows platform, and met the problem specified in the title. The problem can be reproduced in 2022.3.39f1, too.
Here is the mini-reproducable C# code
using System;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
IntPtr nativeHandle = new IntPtr(12345986);
ReleaseNative(ref nativeHandle);
int data = 12;
ReleaseNative2(ref data);
}
static void fun(IntPtr ptr)
{
Debug.Log("test pointer" + ptr);
}
static void ReleaseNative(ref System.IntPtr nativeObjectPtr)
{
if (nativeObjectPtr != System.IntPtr.Zero)
{
var tmp = nativeObjectPtr;
nativeObjectPtr = System.IntPtr.Zero;
fun(tmp);
}
}
static void fun2(int num)
{
Debug.Log("test int " + num);
}
static void ReleaseNative2(ref int data)
{
if (data != 0)
{
var tmp = data;
data = 0;
fun2(tmp);
}
}
}
and the code generated by il2cpp when development is closed is listed below
// System.Void Test::ReleaseNative(System.IntPtr&)
IL2CPP_EXTERN_C IL2CPP_METHOD_ATTR void Test_ReleaseNative_m7B00509CB5DA0522106A58FEBC5118E987BF1998 (intptr_t* ___0_nativeObjectPtr, const RuntimeMethod* method)
{
static bool s_Il2CppMethodInitialized;
if (!s_Il2CppMethodInitialized)
{
il2cpp_codegen_initialize_runtime_metadata((uintptr_t*)&IntPtr_t_il2cpp_TypeInfo_var);
s_Il2CppMethodInitialized = true;
}
{
// if (nativeObjectPtr != System.IntPtr.Zero)
intptr_t* L_0 = ___0_nativeObjectPtr;
intptr_t L_1 = ((IntPtr_t_StaticFields*)il2cpp_codegen_static_fields_for(IntPtr_t_il2cpp_TypeInfo_var))->___Zero_1;
bool L_2;
L_2 = IntPtr_op_Inequality_m90EFC9C4CAD9A33E309F2DDF98EE4E1DD253637B(((*(L_0))), L_1, NULL);
if (!L_2)
{
goto IL_001c;
}
}
{
// var tmp = nativeObjectPtr;
intptr_t* L_3 = ___0_nativeObjectPtr;
// nativeObjectPtr = System.IntPtr.Zero;
intptr_t* L_4 = ___0_nativeObjectPtr;
intptr_t L_5 = ((IntPtr_t_StaticFields*)il2cpp_codegen_static_fields_for(IntPtr_t_il2cpp_TypeInfo_var))->___Zero_1;
*((intptr_t*)L_4) = (intptr_t)L_5;
// fun(tmp);
Test_fun_mAA5F3D0820F1DADB63841141BBDA24CAF0E9DE0D(((*(L_3))), NULL);
}
IL_001c:
{
// }
return;
}
}
and the code generated by il2cpp when development is open is listed below
// System.Void Test::ReleaseNative(System.IntPtr&)
IL2CPP_EXTERN_C IL2CPP_METHOD_ATTR void Test_ReleaseNative_m7B00509CB5DA0522106A58FEBC5118E987BF1998 (intptr_t* ___0_nativeObjectPtr, const RuntimeMethod* method)
{
static bool s_Il2CppMethodInitialized;
if (!s_Il2CppMethodInitialized)
{
il2cpp_codegen_initialize_runtime_metadata((uintptr_t*)&IntPtr_t_il2cpp_TypeInfo_var);
s_Il2CppMethodInitialized = true;
}
bool V_0 = false;
intptr_t V_1;
memset((&V_1), 0, sizeof(V_1));
{
// if (nativeObjectPtr != System.IntPtr.Zero)
intptr_t* L_0 = ___0_nativeObjectPtr;
intptr_t L_1 = ((IntPtr_t_StaticFields*)il2cpp_codegen_static_fields_for(IntPtr_t_il2cpp_TypeInfo_var))->___Zero_1;
bool L_2;
L_2 = IntPtr_op_Inequality_m90EFC9C4CAD9A33E309F2DDF98EE4E1DD253637B(((*(L_0))), L_1, NULL);
V_0 = L_2;
bool L_3 = V_0;
if (!L_3)
{
goto IL_0024;
}
}
{
// var tmp = nativeObjectPtr;
intptr_t* L_4 = ___0_nativeObjectPtr;
V_1 = ((*(L_4)));
// nativeObjectPtr = System.IntPtr.Zero;
intptr_t* L_5 = ___0_nativeObjectPtr;
intptr_t L_6 = ((IntPtr_t_StaticFields*)il2cpp_codegen_static_fields_for(IntPtr_t_il2cpp_TypeInfo_var))->___Zero_1;
*((intptr_t*)L_5) = (intptr_t)L_6;
// fun(tmp);
intptr_t L_7 = V_1;
Test_fun_mAA5F3D0820F1DADB63841141BBDA24CAF0E9DE0D(L_7, NULL);
}
IL_0024:
{
// }
return;
}
}
The parameter passed to the function fun will be Inptr.Zero when the development build is open, which is undesirable.
And if the type is int instead of System.Inptr, the problem is missing.
Does anyone know what happens behind the IL2CPP? How does development build affect the code generation in il2cpp?