2012-04-05 7 views
2

私のプログラムブレークの完全に無関係の行にセグメンテーションフォールトが発生し、ここにEXC_BAD_ACCESSを与えますそのコード行は後のコード行です。後で呼び出されない関数では、プログラムを破損しているようなコード行があります。行が実行される前に関数から復帰するとプログラムにはこの問題はありませんが、行の後の関数から復帰するはずです。この問題があります。ラインは、Xcodeで、スタックトレースによると、コード

コード行は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->型にはcl_mem型があります。 err、pおよびxはint型です。

"Apple LLVM Compiler 3.0"でXcodeを使用しています。 "LLVM GCC 4.2"コンパイラは、何らかの理由で "アーキテクチャi386用の不正なメタデータレコード"を返します。

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[]) { 

をプログラムが直ちに終了し、コマンドラインで直接実行している場合:コンパイルとGDBで実行するコマンドラインを使用した場合

これが結果です。

+3

プログラムが 'gdb'でクラッシュした後に' bt'の出力をポストできますか? –

+1

Valgrind? –

+2

'main'の2番目のパラメータに' const'を付けずに試しましたか? [C99標準](http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1256.pdf)は、それを平文の 'char **' ... – pmg

答えて

8

良い推測のためのMrGomezのおかげで、実際の答えは私の顔を見つめています。答えはこのウェブサイトの名前です。問題は、メイン関数の自動変数が大きすぎてスタックオーバーフローを引き起こしたことです。解決策は、mallocを使用してデータを割り当てることでした。

これはGoogleから見ると、宣言された変数の大きさを確認することをお勧めします。実行時にメモリを割り当てることができます。

+0

+1と定義しています。ええ、これらのケースでは、あなたの割り当てを積極的に活用すれば問題は解決します。それは明らかにスタックの問題だったが、それは私の外にあったようだ。 :) – MrGomez

+0

(賞金期間中にこれを行うことができるのであれば、この回答に印を付けるのが賢明かもしれませんが、これは問題に対するあなたの解決策を認識していないように見えます) – MrGomez

+0

はい、あります。あなたはすぐに自分の答えを受け入れることはできません。 –

2

clEnqueueReadBuffervoid*バッファポインタを使用して(*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があり、OSXの場合はother toolsが存在します。

あなたのアプリケーションに幸運。あなたのバッファで安全にプレイしてください。あなたのプログラムは引き続き幸せになれます。 :)

編集:閉じるが、nope

0

呼び出されていない関数のように、コード内の奇妙な場所で不具合が発生した場合、破損したコードポインタを介して間接的にジャンプする可能性があります。これは、プログラム内で値として見える関数ポインタである必要はありません。それはスタック上の壊れたリターンアドレスかもしれません。

以前の関数呼び出しの連鎖(スタックのビットとピースがまだ残っている)で以前に使用されていた戻りアドレスを使用して、マシンが自分自身をだますことができます。

例。あなたのload_pricesfopenと呼ばれているので、スタックに戻りアドレスが書き込まれます。その後、ビジネス全体が返され、プログラムは、戻りアドレスが上書きされないように、関数の他の起動チェーンを呼び出しています。 (関数がローカル変数を割り当てても完全に初期化しないこともあるし、レジスタセーブ領域などのスクラッチ領域を配列することもありますが、必ずしもそれらを使用するとは限りません)

とにかく、 fopenに与えられた古い戻りアドレスが再利用されるように誤った関数の戻り値が実行されます。 Blam、fopenからもう一度戻るように、load_pricesの中に戻ります(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); 

そこには、あまりにも多くの安全に1行のコードとして維持するためにここで起こっています。

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 
} 
関連する問題