しばらく時間と労力を費やした後、コード内のメモリ破壊バグをこの関数に突き止めました。__block vector<int>
2 つの変数を、ストレージを提供するスタック割り当て配列と、ブロック内のコードが配列にアクセスできるようにする変数の組み合わせに置き換えることで、メモリ破壊を止めました{klist|dlist}Ptr
(以下の推奨コードを参照)。これは、実際に問題があるのは の使用であると確信しています__block vector<int>
。
void
traceTree(Matrix<double> Z, double s[3], int k, unsigned int depth)
{
int m = Z.size(1) + 1;
__block vector<int> klist(m, 0);
// int klist[m]; int * klistPtr = klist;
// klist[0] = k;
__block vector<int> dlist(1, depth);
// int dlist[depth]; int * dlistPtr = dlist;
// dlist[0] = depth;
__block int topk = 0;
int currk = 0;
void (^ subtree)(int i) = ^(int i) {
if (i > m) { // If it's not a leaf...
topk += 1;
klist[topk] = i - m;
dlist[topk] = depth - 1;
}
};
while (currk <= topk) {
k = klist[currk];
depth = dlist[currk];
s[0] += Z[{2,k}]; // Sum of the edge lengths so far
s[1] += Z[{2,k}] * Z[{2,k}]; // ... and the sum of the squares
s[2] += 1; // ... and the count of the edges
if (depth > 0) {
subtree(Z[{0,k}]); // Consider left subtree
subtree(Z[{1,k}]); // Consider right subtree
}
currk += 1;
}
}
[指摘しておきますが、これは純粋に反復的なアルゴリズムです。再帰はありません。このブロックは、左右のサブツリーを処理するために必要なコードの重複を避けるためにのみ存在します。]
明らかな疑問は、なぜ STLvector
オブジェクトがここでメモリ破損を引き起こしているのかということです。__block
彼らは動的なサイズ変更すら行っていません... C++ オブジェクトを変数として使用することは単にサポートされていないのでしょうか?