1. 程式人生 > >Bus error的解決方法

Bus error的解決方法

在x86+Linux上寫的程式,在PC機上執行得很好。可是使用ARM的gcc進行交叉編譯,再送到DaVinci目標板上執行的時候,出現了Bus error。
出現的位置如下(其中Debug的內容是我在程式中新增的除錯資訊):
[email protected]:~# arm_v5t_le-gcc -g shit.c
[email protected]:~# ./a.out
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52
Bus error
開啟偵錯程式進行除錯:
[email protected]
:~# gdb a.out
GNU gdb 6.3 (MontaVista 6.3-20.0.22.0501131 2005-07-22)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "armv5tl-montavista-linuxeabi"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) run // 執行程式
Starting program: /home/zpf/a.out
Debug: in get_program_info()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send LIN_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: gonna receive LIN_RSP
Debug: in my_recvn()
Debug: nleft = 3
Debug: received first 3 bytes from server: 7
Debug: gonna check if 3rd byte is the package type
Debug: received package length = 55
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52

Program received signal SIGBUS, Bus error. // 在這裡出現了錯誤
0x00009624 in alloc_prog_mem (detail_buf=0x13118 "/001/002",
err_buf_ptr=0xbefffc40 "") at shit.c:631
631 g_data_ptr->progtype_num = *(short *)ptr ;
(gdb) print ptr // 檢視一下ptr的值

$1 = 0x13119 "/002" // 地址起始是奇數!!!
(gdb) set ptr=0x1311a// 想改一下
(gdb) continue
Continuing.

Program terminated with signal SIGBUS, Bus error.
The program no longer exists. // 可惜程式已經退出
(gdb) quit

其中,g_data_ptr->progtype_num是一個short型別的值。
把強制型別轉換改為用memcpy()寫值之後,再除錯
[email protected]:~# gdb test
GNU gdb 6.3 (MontaVista 6.3-20.0.22.0501131 2005-07-22)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "armv5tl-montavista-linuxeabi"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) break 626 // 把剛剛的那句強制型別轉換變成記憶體拷貝
Breakpoint 1 at 0x9630: file test.c, line 626.
(gdb) run
Starting program: /home/zpf/test
Debug: in get_program_info()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send LIN_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: gonna receive LIN_RSP
Debug: in my_recvn()
Debug: nleft = 3
Debug: received first 3 bytes from server: 7
Debug: gonna check if 3rd byte is the package type
Debug: received package length = 55
Debug: malloc space for the actual data: temp_buf = 0x13118
Debug: in my_recvn()
Debug: nleft = 52

Breakpoint 1, alloc_prog_mem (detail_buf=0x13118 "/001/002",
err_buf_ptr=0xbefffc40 "") at test.c:626
warning: Source file is more recent than executable.

626 memcpy(&(g_data_ptr->prog_num), ptr, 2) ; // 在這一句中斷

(gdb) print ptr // 再看看ptr
$1 = 0x1311b "/003" // 還是奇數地址
(gdb) continue // 繼續執行
Continuing.
Debug: sum_progtype = 2 , sum_prog = 3
Debug: gonna malloc space for progtype_ptr
Debug: gonna malloc space for prog_ptr
Debug: in mv_pkg2prog_list()
Debug: gonna set ProgramType program_type_name
Debug: ProgramType program_type_name set OK
Debug: in $ == *ptr, j = 0
Debug: g_data_ptr->progtype_ptr[j].prog_ptr = temp_prog_ptr
Debug: in @ == *ptr, ptr = 0x13126
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
Debug: in @ == *ptr, ptr = 0x1312f
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
Debug: gonna set ProgramType program_type_name
Debug: ProgramType program_type_name set OK
Debug: in $ == *ptr, j = 1
Debug: g_data_ptr->progtype_ptr[j].prog_ptr = temp_prog_ptr
Debug: in @ == *ptr, ptr = 0x13142
Debug: temp_prog_ptr->format = *ptr
Debug: temp_prog_ptr->program_id = *(int *)ptr
Debug: gonna set Program program_name
Debug: Program program_name set OK
Debug: finished one loop of while
program type[0]
program_type_id = 1
program_type_name = love
program_num = 2
prog_ptr = 0x131d8
program[0]
program_id = 1001
program_name = you
format = 1
program[1]
program_id = 1002
program_name = me
format = 2
program type[1]
program_type_id = 2
program_type_name = hatred
program_num = 1
prog_ptr = 0x13248
program[0]
program_id = 2005
program_name = kill
format = 5
Debug: gonna return an OK
Debug: Entering send_exit_requstion()
Debug: in conn_server(char *err_buf_ptr)
Debug: gonna create a socket
Debug: gonna fill in the serv_addr structure
Debug: gonna connect to a server
Debug: gonna send EXIT_RST
Debug: in my_sendn()
Debug: send 4 bytes to server:
Debug: in my_recvn()
Debug: nleft = 4
Debug: gonna return an OK

Program exited normally. // 執行通過了!!!!
(gdb)

總結:
問題總算找到了,就是我企圖在一個奇數地址起始的地方強制型別轉換得到一個short值。
在Intel系列處理器上,可以在任一奇數記憶體地址儲存任何變數或陣列,不會導致任何致命的錯誤影響,只是效率可能會降低。但在DaVinci上,這一點不行。所以必須對大於一個位元組的資料型別小心謹慎,比較安全的方法是使用記憶體拷貝函式memcpy(),或者使用下面的代替方法:
// 先定義一個聯合體
union {
short short_val ;
char short_byte[2] ;
} myshort ;
// 然後,把程式中本來應該是
// g_data_ptr->progtype_num = *(short *)ptr ;
// ptr += 2 ;
// 這兩句的地方換成下面五句:
myshort.short_byte[0] = *ptr ;
ptr++ ;
myshort.short_byte[1] = *ptr ;
ptr++ ;
g_data_ptr->progtype_num = myshort.short_val ;
// 當然,最簡單的方法是換成下面兩句:
// memcpy(&(g_data_ptr->progtype_num), ptr, 2) ;
// ptr += 2 ;

對於這個問題的進一步探討:

在DaVinci上應該注意記憶體編址模式的問題。
struct {
char struc_char ;
int struc_int ;
short struc_short ;
long struct_long ;
} struc_val ;
在寬鬆模式下,儘管struc_char只有1個位元組,struc_short佔2個位元組,但編譯器可能給這兩個變數分別分配了4個位元組,結果整個結構的大小變成了16個位元組,而在編譯器設為緊湊模式時,則正好是11個位元組。根據計算機資料匯流排的位數,不同的編址模式存取資料的速度不一樣。我認為在符合匯流排字長的情況下,效率是最高的,因為只需進行一次匯流排操作。
記憶體編址模式會影響位元組對齊方式,位元組對齊操作可以解決以下兩個主要的問題:
1.訪存效率問題;一般的編譯器要對記憶體進行對齊,在處理變數時,編譯器會根據一定的設定將長短不同的變數的資料長度進行對齊以加快記憶體處理速度。
2.強制型別轉換問題:在x86上,位元組不對齊的操作只會影響效率,但是在DaVinci上,可能就是一個Bus error, 因為它要求必須位元組對齊。
位元組對齊的準則
1.資料型別自身的對齊值:對於char型資料,其自身對齊值為1,對於short型為2,對於int,long,float,double型別,其自身對齊值為4位元組。
2.結構體的自身對齊值:其成員中自身對齊值最大的那個值。
3.指定對齊值:#pragma pack (value)時的指定對齊值value。
4.資料成員、結構體和類的有效對齊值:自身對齊值和指定對齊值中小的那個值。
對於平時定義變數,儘可能先定義長度為4的倍數的變數,然後是長度是2的變數,最後是長度為1的變數。

通過測試,GCC編譯器是按照4位元組對齊存放於記憶體的。而我還沒有發現更改編址模式的引數。程式如下:
#include

相關推薦

設置MiniUI Datagrid setData錯誤json error解決方法

miniui datagrid背景公司購買的MiniUI,改造現有項目Table表格時,官網API未提供靜態數據案例,導致各種失敗解決方案上官網論壇,看到有人說grid.load()是相對於url使用的,去掉就好了正確的setData使用方法 <div id="datagridTabl

關於在地址池下綁定IP時報錯The IP address‘s status is error解決方法

key src gb2 c99 blob 電腦 oss ont ror 我使用華為交換機為一家企業裏電腦綁定IP地址時報:The IP address's status is error的錯誤。如下圖: 這時我覺得可能這個IP地址已經被DHCP服務給分配到

Appium移動端自動化測試-常見error解決方法

1:Original error: Could not extract PIDs from ps output. PIDS: [], Procs: ["bad pid 'uiautomator'"] 解決方法:https://blog.csdn.net/u012106209/article/de

Keil "st-link usb communication error"解決方法

Keil "st-link usb communication error" 解決方法     今天碰到了“st-link usb communication error“的問題,在網上找了好多的資料,測試了好多的方法,最終才解決問題。在此貼出來,希望能夠幫助到遇到同樣問題的

VMware unrecoverable error解決方法

把開發環境部署在虛擬機器裡面,重灌系統後不需要再重複部署開發環境。但是有時候異常退出虛擬機器會導致錯誤。之前出現開啟虛擬機器之後,系統解析度錯誤,就是點選的位置和顯示的位置不一樣。於是重新關了虛擬機器,這時候虛擬機器佔用cpu 100%,過了很長時間都沒有關閉成功。於是直接

setContentView(R.layout.activity_main) Error解決方法

今天在寫Android程式碼的過程中,編譯器一直報錯,錯誤出在這一行程式碼: <span class="pln" style="margin: 0px; padding: 0px;">setContentView</span><span cl

9341 openwrt新增usb led後出現出現SQUASHFS error解決方法

[   12.290000] SQUASHFS error: squashfs_read_data failed to read block 0x2a92ce [   12.300000] SQUASHFS error: Unable to read fragment cache entry [2a92ce]

500 Internal Server Error解決方法

suEXEC Problems ...and how to fix them. When running a Perl CGI script, you may see the "premature end of script headers" error in

rosdep init and update Error 解決方法

rosdep init and update Error rosdep init Error $ sudo rosdep initERROR: default sources list file already exists: /etc/ros/rosdep/source

windows下pytorch import error解決方法

在最新的0.4.0版本中,pytorch已經開始支援Windows環境了,只需要在www.pytorch.org首頁上選擇對應的版本即可。但是在安裝完成後,有可能會遇到以下問題:from torch._C import * ImportError: DLL load fai

Bus error解決方法

在x86+Linux上寫的程式,在PC機上執行得很好。可是使用ARM的gcc進行交叉編譯,再送到DaVinci目標板上執行的時候,出現了Bus error。出現的位置如下(其中Debug的內容是我在程式中新增的除錯資訊):[email protected]:~# arm_v5t_le-gcc -g

HTTP 錯誤 500.19 Internal Server Error解決方法

輸入a dpi 編輯 模塊 cfi modules 位置 override 程序 第一種可能,能解決一部分問題 http://wenku.baidu.com/view/c5cb4a08bb68a98271fefa3f.html 第二種可能,解決另外一部分問題 經過檢查發

VC6的工程轉到VC2010或更高版本出現fatal error C1189編譯錯誤的解決方法

代碼 ram 選擇 spa file 線程 c11 靜態庫 block 以前也遇到過,當時解決了沒寫下來,這次正好又遇到了,就順手寫一下吧,別下次又忘記了。 當VC6的工程轉到VC2010或更高版本時編譯出現如下錯誤: c:\program files\micros

Error, some other host already uses address 192.168.0.202錯誤解決方法

機器 虛擬機網卡 一個 already 局域網 使用 sysconf erro 錯誤 Error, some other host already uses address 192.168.0.202錯誤解決方法 今天配置虛擬機網卡的時候遇到錯誤:Error, so

dpkg: error processing package bluez (--configure) 解決方法【轉】

operation proc addition too opera report add message ace 轉自:http://blog.csdn.net/heray1990/article/details/47803541 在 Ubuntu 執行 sudo apt

安裝Matlab出現Error 1935錯誤解決方法

技術 啟動 運行 十進制 gist log ror oca 下拉菜單 1、開始 - 運行(輸入regedit.exe)- 確定或者回車,打開註冊表編輯器; 2、在打開的註冊表編輯器中找到:HKEY_LOCAL_MACHINE ,並展開:HKEY_LOCAL_MACHINE

urllib2.HTTPError: HTTP Error 403: Forbidden 解決方法

error ack mac int ins com Language gzip ces 參考: https://stackoverflow.com/questions/13303449/urllib2-httperror-http-error-403-forbidden

Redis (error) NOAUTH Authentication required.解決方法

style data- itl digg ews command root details tools 出現認證問題,應該是設置了認證密碼,輸入密碼既可以啦 註意密碼是字符串形式! [plain] view plain copy 127.0.0.1:6379&

ERROR: JDWP Unable to get JNI 1.2 environment的解決方法

pre 發生 next ret bsp println 資料 new 獲取 當執行如下代碼時: //從控制臺獲取輸入 InputStream is = System.in; Scanner scanner = new Sca

關於mysql登錄出現報錯信息:ERROR 1045 (28000)的解決方法

myql 登錄 error 1045 登錄mysql數據庫出現報錯信息ERROR 1045(28000)如下:[[email protected] ~]# mysql -uroot -p fanshine Enter password: ERROR 1045 (28000): Acce