1

我有一个 C++ 程序,主要执行矩阵乘法、加法等。

问题是,当计算执行大约 300 万次时会发生 EXC_BAD_ACCESS。

当一个问题被执行数百万次和几个小时时,是否会出现任何可能的问题?

节目详情:

该程序只是对不同范围的值进行计算,因此它同时在 6 个线程上执行。线程之间没有资源共享。

该程序似乎没有明显的问题,因为:

  1. 没有内存泄漏,我用 Instruments 确认过,程序的内存大小是稳定的。
  2. 该程序可以在每个线程上执行至少 200 万次而没有任何问题,但几乎可以保证 EXC_BAD_ACCESS 异常在某个时间出现在某个线程上。(异常发生在我的 2 次程序尝试 (2/2) 中)

关于矩阵乘法:

有时矩阵的大小约为 2*2 乘以 2*1000。

矩阵的元素是一个自定义的复数类。

元素的值由 rand() 随机生成并转换为浮点数。

结构是这样的:

class Complex
{
private:
    float _real, _imag;
public:
   // getters, setters and overloaded operators
};

class Matrix
{
private:
    Complex **_values;
    int _row,_col;
public:
     getters, setters and overloaded operators
};

非常感谢!

非常欢迎任何可能的崩溃原因!

4

3 回答 3

2

EXC_BAD_ACCESS 意味着您取消引用了一个不指向进程当前内存空间的指针。这是您的代码中的一个错误。在调试器下运行它直到它失败,然后查看它失败的语句中的变量值。它可能很简单,也可能非常微妙。

于 2013-09-22T00:46:28.333 回答
1

您的帖子中的信息太少,无法做出决定性的回答。但是,您现在可能没有可用的信息会更改它,您需要更仔细地调试案例。这就是我要做的。

要调试,您需要可重复性。但是……你说你使用的是随机数。不过,您的程序所做的似乎是一些科学计算。在大多数情况下,您实际上并不需要“真正的”随机性,而是“可重复的”随机性——通过统计测试的随机性,但是您有足够的数据来重置随机数生成器,以便它产生与中完全相同的结果上一次运行。为此,您可以在每次开始新的计算块时记下当前的 RNG 状态(例如种子)。

现在,编写一些代码来存储所有必要的状态,以每隔几分钟重新启动一次计算(包括 RNG),然后运行程序。这样,如果您的代码崩溃,您将能够以相同的确切状态重新开始计算并到达崩溃的地步,而无需等待数百万次迭代。我在这里提出一个强有力的假设,即除了 RNG,您的代码不依赖于任何其他类型的外部状态(例如,网络活动、IO、进程调度程序在调度线程时做出某些选择……)

有了这种数据,就可以更容易地测试问题是否是由于机器故障(过热、内存不足等)造成的。只需使用崩溃前的最后一个状态重新启动计算 - 最好在让机器冷却之后,也许重新启动它......如果你会遇到另一个崩溃(每次尝试重新启动代码时都会发生),很确定这是由于您的代码中的错误。

如果不是,我们仍然不能说这是机器故障——您的代码可能(由于代码中的纯意外/错误)由于取决于您无法控制的因素的未定义行为而崩溃。示例包括在很少使用的代码路径中使用未初始化的指针:它有时可能会引发错误的访问,并且如果纯粹靠运气指针指向您分配的内存,则不会被注意到。试试valgrind,这可能是检查内存问题的最佳工具……除了它会大大减慢执行速度,以至于您会再次喜欢从已知可疑的状态(崩溃前的最后一个状态)重新运行计算,而不是等待数百万次迭代。我已经看到了 5 倍到 100 倍的减速。

同时,尝试在另一台机器上运行您的代码。如果在类似数量的迭代后您也会崩溃(确保等待至少比原始机器崩溃多 3 倍的迭代次数),那么很可能这是您的代码中的错误。

快乐黑客!

于 2013-09-22T01:19:43.113 回答
0

在几百万次迭代后失败的有限精度计算?这可能是累积的舍入误差。问题是,这些通常表现为除以零或其他数学错误。EXC_BAD_ACCESS不是。但是,有一种情况会发生这种情况:当您将数学结果用作数组索引时。

于 2013-09-22T22:22:02.687 回答