signal 7 (SIGBUS), code 1 (BUS_ADRALN) caused the crash

  android, c#, il2cpp, memory-alignment, unity3d

Maybe my technical level is not enough, this question makes me very difficult to understand!
I have a program that can write Buffer,this is the code

 public class WriteBuffer
 {

    private byte[] beginPtr;

    private int position;

    private int length;

    public WriteBuffer(int len)
    {
        beginPtr = new byte[len];
        position = 0;
        length = 0;
        if (beginPtr != null)
        {
            length = len;
        }
    }

    public PbError.ErrorType writeUInt8(byte src)
    {
        if (beginPtr == null)
        {
            return PbError.ErrorType.PB_ERR_ARG_IS_NULL;
        }

        if (1 > length - position)
        {
            return PbError.ErrorType.PB_ERR_WRITE_BUFF_INSUFFIX;
        }

        beginPtr[position++] = src;
        return PbError.ErrorType.PB_NO_ERROR;
    }

    public PbError.ErrorType writeInt32(int src)
    {
        if (beginPtr == null)
        {
            return PbError.ErrorType.PB_ERR_ARG_IS_NULL;
        }

        if (4 > length - position)
        {
            return PbError.ErrorType.PB_ERR_WRITE_BUFF_INSUFFIX;
        }

        if (BitConverter.IsLittleEndian)
        {
            src = IPAddress.HostToNetworkOrder(src);
        }

        WriteBytes(src, beginPtr, ref position);
        return PbError.ErrorType.PB_NO_ERROR;
    }

    public PbError.ErrorType writeInt64(long src)
    {
        if (beginPtr == null)
        {
            return PbError.ErrorType.PB_ERR_ARG_IS_NULL;
        }

        if (8 > length - position)
        {
            return PbError.ErrorType.PB_ERR_WRITE_BUFF_INSUFFIX;
        }

        if (BitConverter.IsLittleEndian)
        {
            src = IPAddress.HostToNetworkOrder(src);
        }

        WriteBytes(src, beginPtr, ref position);
        return PbError.ErrorType.PB_NO_ERROR;
    }

    public unsafe void WriteBytes(int val, byte[] dest, ref int offset)
    {
        if (dest == null)
        {
            throw new ArgumentNullException("dest");
        }

        if (offset < 0 || offset + 4 > dest.Length)
        {
            throw new ArgumentNullException("offset");
        }

        fixed (byte* ptr = dest)
        {
            *(int*)(ptr + offset) = val;
        }

        offset += 4;
    }

    public unsafe void WriteBytes(long val, byte[] dest, ref int offset)
    {
        if (dest == null)
        {
            throw new ArgumentNullException("dest");
        }

        if (offset < 0 || offset + 8 > dest.Length)
        {
            throw new ArgumentNullException("offset");
        }

        fixed (byte* ptr = dest)
        {
            *(long*)(ptr + offset) = val;
        }

        offset += 8;
    }
}

and a test code here:write byte value first

public class Main : MonoBehaviour
{
    private byte byte1;
    private long long1;
    private int int1;
 
    private const string LOG_FILTER_TAG = "SELF_LOG: ";
    WriteBuffer writeBuf = new WriteBuffer(1024);
 
    private void Start()
    {
        byte1 = 1;
        long1 = 10L;
        int1 = 100;
    }
 
    private void OnGUI()
    {
        if (GUILayout.Button("Write To Buffer", GUILayout.Height(100f), GUILayout.Width(200f)))
        {
            //write byte
            var ret = writeBuf.writeUInt8(byte1);
            Debug.Log(LOG_FILTER_TAG + (ret == PbError.ErrorType.PB_NO_ERROR ? "Byte Success" : ret.ToString()));
            //write long
            ret = writeBuf.writeInt64(long1);
            Debug.Log(LOG_FILTER_TAG + (ret == PbError.ErrorType.PB_NO_ERROR ? "long Success" : ret.ToString()));
            //write int
            ret = writeBuf.writeInt32(int1);
            Debug.Log(LOG_FILTER_TAG + (ret == PbError.ErrorType.PB_NO_ERROR ? "int Success" : ret.ToString()));
 
        }
    }
}
 

I made an Android apk which scripting backend is IL2CPP RELEASE and ran it .The crash happened when I executed the code in OnGUI.The log found this content:signal 7 (SIGBUS), code 1 (BUS_ADRALN) !This means there is a problem with the memory alignment,Then I used libil2cpp.sym.so to locate the problem in the line of code

 *(long*)(ptr + position) = val;

I guess this may be because I first wrote a byte, and then wrote a long at the offset + ptr, but the address of this position is not a multiple of 8, so it crashed.
Then I changed my code:write long value first

    private void OnGUI()
    {
        if (GUILayout.Button("Write To Buffer", GUILayout.Height(100f), GUILayout.Width(200f)))
        {
           
            //write long
           var ret = writeBuf.writeInt64(long1);
            Debug.Log(LOG_FILTER_TAG + (ret == PbError.ErrorType.PB_NO_ERROR ? "long Success" : ret.ToString()));
            //write byte
            ret = writeBuf.writeUInt8(byte1);
            Debug.Log(LOG_FILTER_TAG + (ret == PbError.ErrorType.PB_NO_ERROR ? "Byte Success" : ret.ToString()));
            //write int
            ret = writeBuf.writeInt32(int1);
            Debug.Log(LOG_FILTER_TAG + (ret == PbError.ErrorType.PB_NO_ERROR ? "int Success" : ret.ToString()));
 
        }
    }

Just such a change does not crash anymore.This is also something that makes me very confused,Why won’t it crash this time.After writing byte, write int again. At this time, offset+ptr is definitely not a multiple of 4, but why doesn’t it crash anymore?Did I understand something wrong?
By the way, the crash is only issued in IL2CPP RELEASE,IL2CPP DEBUG or Mono will not.

Source: Android Questions

LEAVE A COMMENT