2012-04-05 72 views
2

我計劃休息一個完全不相關的線分段錯誤,在這裏給出了EXC_BAD_ACCESS,根據堆棧跟蹤在Xcode:行導致對代碼

int main (int argc, const char * argv[]) { 
    float usd,btc,bid,ask,order_price,possible_price; 
    DateData * prices = load_prices(); <--- 

DateData * load_prices(){ 
    FILE * file = fopen("price.dat", "rb"); <--- 

我確定這有沒有關係該代碼行,但後面的一行。在稍後不調用的函數中,有一行代碼似乎破壞了程序。當它在執行行之前從函數返回時,程序沒有這個問題,但是如果它應該從行之後的函數返回,則會出現此問題。

代碼行是對OpenCL的調用。它以某種方式破壞該程序?

err = clEnqueueReadBuffer(ocl_data->commands, ocl_data->output, CL_TRUE, 0, sizeof(CombinationResult) * PPO_COMBINATIONS, (*PPO_results)[x] + PPO_COMBINATIONS*(p + 5), 0, NULL, NULL); 

PPO_COMBINATIONS被定義爲整數的宏和PPO_results的類型是CombinationResult(*)[3] [PPO_COMBINATIONS * 11]。 ocl_data->命令的類型爲cl_command_queue,ocl_data-> output的類型爲cl_mem。 err,p和x的類型爲int。

我正在使用Xcode和「Apple LLVM Compiler 3.0」。出於某種原因,「LLVM GCC 4.2」編譯器給出了「架構i386的格式錯誤的元數據記錄」。

這是使用命令行編譯並用gdb運行時的結果:

Matthew-Mitchell:Parrallel BitCoin Trading Algorithm matt$ gcc -g cmain.c -o test -lcurl -framework OpenCL -std=c99 -arch i386 
Matthew-Mitchell:Parrallel BitCoin Trading Algorithm matt$ gdb testGNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Mon Aug 15 16:03:10 UTC 2011) 
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 "x86_64-apple-darwin"...Reading symbols for shared libraries .... done 

(gdb) run 
Starting program: /Users/matt/Programming/Bit Coin algorithm/Parrallel BitCoin Trading Algorithm/test 
Reading symbols for shared libraries .+++.................................................................. done 

Program received signal EXC_BAD_ACCESS, Could not access memory. 
Reason: KERN_PROTECTION_FAILURE at address: 0xbea7d7cc 
0x00003e9a in main (argc=0, argv=0x1000) at cmain.c:572 
572 int main (int argc, const char * argv[]) { 

當在命令行直接運行該程序立即退出。

+3

你可以在'gdb'程序崩潰後發佈'bt'的輸出嗎? – 2012-04-08 16:38:07

+1

你有沒有在例如Valgrind的? – 2012-04-08 16:40:33

+2

你嘗試沒有'const'在'main'第二放慢參數? [C99標準](http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1256.pdf)將其定義爲簡單的'char **'... – pmg 2012-04-08 16:55:41

回答

8

感謝MrGomez的一個很好的猜測,但實際的答案一直盯着我的臉。答案就是這個網站的名稱。問題是主函數中的自動變量太大,導致堆棧溢出。解決方案是使用malloc分配數據。

對於任何人看到這從谷歌,這是一個好主意,檢查你的聲明變量有多大。您可能想要在運行時分配內存。

+0

+1。是的,在這些情況下,分配您的分配將解決問題。這顯然是一個堆棧問題,但看起來,哪一個是超越我的。 :) – MrGomez 2012-04-09 18:08:38

+0

(在賞金期間,如果你能夠這樣做的話,這可能是明智的做法,這可能是明智的做法,但這似乎並不認識你解決問題的方法。) – MrGomez 2012-04-14 15:38:09

+0

是的,它是一個恥辱,你不能立即接受你自己的答案。 – 2012-04-15 15:02:45

2

我要帶胡亂猜測,說你已經堆棧損壞當您試圖通過void*緩衝區指針在clEnqueueReadBuffer寫進去(*PPO_results)[x] + PPO_COMBINATIONS*(p + 5)。我很容易相信整數宏PPO_COMBINATIONS和指針操作PPO_results的組合會指向堆棧,導致您意外地寫入應用程序的可執行區域。

如果它將您撥打電話的區域打入FILE * file = fopen("price.dat", "rb");,這會重現您所看到的問題。作爲獎勵,這會阻止像gdb這樣的工具正確解開堆棧幀(從而禁止完整的堆棧跟蹤),因爲在那時,堆棧處於損壞且無法恢復的狀態。

最簡單的檢查方法是通過在調試器中逐步完成寫入操作或在應用程序上運行bounds checker。 Valgrind has a patch containing this functionality和幾個other tools也存在於這個OSX的空間中。

祝您的應用程序順利。用你的緩衝區安全地玩,你的程序將繼續快樂。 :)

編輯:關閉,但是,nope

0

當發生故障,在代碼中的一些奇怪的地方,像一個甚至不是被調用函數,它可能是由於通過破壞碼指針間接跳轉。這不一定是一個函數指針,它在程序中作爲一個值可見。它可能是堆棧上的一個損壞的返回地址。

機器有可能使用先前在前一個函數調用鏈(其中仍然有一些零件位於堆棧中)中使用的返回地址來自我回報。

例子。你load_pricesfopen,所以它把返回地址壓入堆棧。然後整個業務都會返回並且程序正在調用其他一些激活功能鏈,這樣就不會覆蓋該返回地址。 (有時函數會分配局部變量但不會完全初始化它們,或者編譯器會安排暫存區域,例如寄存器保存區域,但並不總是使用它們。)

無論如何,有些東西變得混亂和不正確的函數返回然後被執行,使得被給fopen舊的返回地址被重新使用。布拉姆,你回來了裏面load_prices彷彿從fopen返回第二次(類似於對setjmp/longjmp的)。

0

打破這一行代碼分成幾行並分配給變量:

err = clEnqueueReadBuffer(ocl_data->commands, ocl_data->output, CL_TRUE, 0, sizeof(CombinationResult) * PPO_COMBINATIONS, (*PPO_results)[x] + PPO_COMBINATIONS*(p + 5), 0, NULL, NULL); 

是有太多的事情在這裏安全地保持儘可能的一行代碼。你還需要更多的錯誤檢查:

if (ocl_data!=null) { 
    //Making Assumtions here, don't expect to compile 
    int crCalc=sizeof(CombinationResult)*PPO_COMBINATIONS; 
    int ppoResult=0; 
    int ppoCFive=PPO_COMBINATIONS*(p + 5); 

    //Check size of PPO_results before assigning 
    if (x<sizeof((*PPO_results)) 
    ppoResult=(*PPO_results)[x]; 

    err = clEnqueueReadBuffer(ocl_data->commands, ocl_data->output, CL_TRUE, 0, crCalc, ppoResult + ppoCFive, 0, NULL, NULL); 
} else (
    //Error message 
}