2

根据 Xcode 中的堆栈跟踪,我的程序在此处中断并给出 EXC_BAD_ACCESS:

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->commands 的类型为 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[]) {

直接在命令行中运行时,程序会立即退出。

4

4 回答 4

8

感谢戈麦斯先生的猜测,但实际答案一直盯着我看。答案是这个网站的名称。问题是主函数中的自动变量太大而导致堆栈溢出。解决方案是使用 malloc 分配数据。

对于从谷歌看到这个的人来说,检查你声明的变量有多大是个好主意。您可能希望在运行时分配内存。

于 2012-04-09T16:39:46.407 回答
2

我要大胆猜测一下,当您尝试(*PPO_results)[x] + PPO_COMBINATIONS*(p + 5)通过. 我很容易相信您的整数宏 ,和您对 combine 的指针操作的组合指向堆栈,导致您意外写入应用程序的可执行区域。void*clEnqueueReadBufferPPO_COMBINATIONSPPO_results

如果它破坏了您调用 into 区域周围的堆栈FILE * file = fopen("price.dat", "rb");,这将重现您所看到的问题。作为奖励,这将阻止某些工具,例如gdb正确展开堆栈帧(从而抑制完整的堆栈跟踪),因为此时堆栈处于损坏且完全不可恢复的状态。

最简单的检查是通过在调试器中逐步执行写入操作或在应用程序上运行边界检查器来验证您的写入。Valgrind有一个包含这个功能的补丁,并且这个空间中还有一些其他的工具存在于 OSX 中。

祝你的申请好运。安全地使用您的缓冲区,您的程序将继续快乐。:)

编辑:关闭,但是,

于 2012-04-08T20:30:44.140 回答
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
}
于 2012-04-12T14:41:04.117 回答
0

当代码中某个奇怪的地方发生错误时,比如一个甚至没有被调用的函数,这可能是由于间接跳转到了损坏的代码指针。这不必是在程序中作为值可见的函数指针。它可能是堆栈上的损坏返回地址。

机器可能会欺骗自己使用之前在之前的函数调用链中使用的返回地址(其中堆栈上仍然有一些零碎)。

例子。您load_prices调用fopen了 ,因此它将返回地址放入堆栈。然后整个业务返回并且程序正在调用一些其他激活函数链,这样返回地址就不会被覆盖。(有时函数分配局部变量但不完全初始化它们。或者编译器安排临时区域,例如寄存器保存区域,但并不总是使用它们。)

无论如何,堆栈出了问题,然后执行了不正确的函数返回,从而fopen重新使用了给定的旧返回地址。Blam,你又回到了里面load_prices,好像fopen第二次回来了(类似于 setjmp/longjmp)。

于 2012-04-12T04:47:39.243 回答