C++成員變量內存對齊問題,ndk下非對齊的內存訪問導致BUS_ADRALN


同樣的代碼,在vs下運行正常,在android ndk下卻崩潰:

signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793

 

Func(short *pVY[])

{

  short *dstY[2] = {pVY[0],pVY[1]};//使用backtrace定位,crash在這一句

}

pVY[0],pVY[1]是從一個統一分配的buffer偏移得來的。

 

1.考慮內存對齊的原因

pVY[0],pVY[1]:0xee25ffe0,0xee262470 。都是32字節對齊的。

重新分配按64字節對齊,pVY[0],pVY[1]:0xee260600,0xee262b00 ,實際已經256字節對齊了,錯誤同樣出現.

不是pVY[0]和[1]內存沒對齊的原因

 

it appears that SIGBUS 7 is a data misalignment issue, and SIGSEGV 11 is a write to inaccessible memory.

打印出pVY的值為0xe6b82793,正好與fault addr一樣,pVY + 1的值為0xe6b82797.

參考:http://stackoverflow.com/questions/13077791/fatal-signal-7-sigbus-at-0x00000000-code-2

 

Linux操作系統會對於 非對齊內存訪問的進程,發送SIGBUS的信號,你的程序,接收到這個信號后,進行coredump,並退出了。

Windows操作系統允許 非地址對齊的內存訪問(會損失性能),所以程序在Windows操作系統下,不會出現error。

Win32平台下的微軟VC編譯器在默認情況下采用如下的對齊規則: 任何基本數據類型T的對齊模數就是T的大小,即sizeof(T)。比如對於double類型(8字節),就要求該類型數據的地址總是8的倍數,而char類型數據(1字節)則可以從任何一個地址開始。Linux下的GCC奉行的是另外一套規則:任何2字節大小(包括單字節嗎?)的數據類型(比如short)的對齊模數是2,而其它所有超過2字節的數據類型(比如long,double)都以4為對齊模數。

 

應該是對pVY,pVY+1的非對齊內存訪問造成的,pVY(0xe6b82793)存的是(short*) pVY[0]。

pVY來自class的成員變量:

class A{

...

short *pVY[6];

};

在vs下調試,pVY 為0x001cd9a8,是8字節對齊的

在ndk下, pVY+0到5為:0xe6b82793,797,79b,79f,7a3,7a7,默認並沒有對齊

解決辦法:

1.不進行賦值,函數體內直接使用形參操作:

Func(short *dstY[])

{

   for(x = 0;x<w;x++){

       dstY[0][x] = x;

       dstY[1][x] = x;

}

}

2.設置內存對齊

 #pragma pack(push) //保存對齊狀態
 #pragma pack(8)//設定為4字節對齊

class A{

...

short *pVY[6];

};

 #pragma pack(pop)

在ndk下pVY的值為0xe6b82794

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM