0

これに似た2つのクラスがあります:

class A
{
public:
    B* ptr1;
}

class B
{
public:
    std::vector<A*> list;
}

主な実装では、次のようなことをしています。

int main() {

// there are a lot more A objects than B objects, i.e. listOfA.size() >>> listOfB.size()
std::vector<A> listOfA;
std::vector<B> listOfB; 

while (//some loop)
{
    listOfB[jj].list.push_back( &(listofA[ii]) );
    listOfA[ii].ptr1 = &( listOfB[jj] );
}

} // int main end

基本的にはこのようなものです。1 つの B オブジェクトに多数の A オブジェクトが割り当てられ、これらの A オブジェクトはそのポインター ベクトルにポインターとして格納されます。さらに、これらの各 A オブジェクトは、それらが属する B オブジェクトへのポインターを取得します。コンテキストについては、基本的に、(画像セグメンテーション用の) ランレングス エンコーディングを使用して連結コンポーネント アルゴリズムを実行しています。ここで、クラス A は線分であり、クラス B は画像内の最終オブジェクトです。

したがって、クラス B のベクトルのポインターはすべて、通常のベクトルに格納されているオブジェクトを指します。これらのオブジェクトは、通常のベクトルが範囲外になったときに削除する必要がありますよね? クラス B のようなポインタのベクトルは、通常、手動のデストラクタを記述する必要があると読みましたが、ここではそうではないと思います...

私が質問している理由は、もちろん、私のコードがクラッシュし続けるからです。Asus Xtion Pro カメラを使用して画像を取得し、すべての画像に対してアルゴリズムを実行しています。奇妙なことに、カメラを少し強く振るとプログラムがクラッシュします。カメラが静止しているか、少しだけまたはゆっくりと動かされている場合、何も起こりません。また、別のアルゴリズム (これも接続されたコンポーネントですが、ランレングス エンコードを使用せず、ポインターも使用しません) を使用すると、カメラをどれだけ振っても何もクラッシュしません。また、デバッグ モード (リリース モードよりもはるかに低速) でも、クラッシュは発生しませんでした。

クラスBでポインタベクトルのデストラクタを作ってみたのですが、「ブロックは有効です」というエラーになったので、何かを2回削除したのでしょう。また、すべてのポインターを c++11 std::shared_ptr に置き換えようとしましたが、非常に不規則な動作しか発生せず、カメラを振るとコードがクラッシュしました。

私は基本的に、メモリ リークとポインタ処理に関して、上記のコードが問題ないように見えるかどうか、またはクラッシュにつながる可能性のあるコードに誤りがあるかどうかを知りたいだけです。

編集(解決済み):解決策(受け入れられた回答を参照)は、実行時にベクトル「listOfB」のサイズが変更されないようにすることでした。たとえば、「reserve()」を使用して十分なスペースを確保することでした。これを行った後、すべてがうまくいきました!ベクトル 'listOfB' が (push_back() によって) サイズ変更されると、その中の B インスタンスの内部メモリ アドレスも変更され、A インスタンス (B インスタンスを指す) のポインタが現在に戻るため、明らかに機能しました。間違ったアドレスを指す - その結果、問題が発生し、クラッシュにつながります。

カメラの揺れについて、明らかに、カメラを振ると、セグメント化する要素が多く、非常にぼやけた写真になり、オブジェクトの数が増えます (つまり、listOfB に必要なサイズが大きくなります)。というわけで謎解き!どうもありがとう!:-)

4

2 に答える 2

2

デザインが壊れていると思います。listofB が大きくなり (push_backs を実行)、その内部データ配列を再割り当てし、A インスタンスの ptr に格納されているすべてのアドレスを無効にします。通常のアルゴリズムでは、データ サイズが 2 倍に拡大されます。これは、大量のデータが到着しなくても、しばらくは問題がないことを示している可能性があります。また、古いデータのメモリがまだプログラムのアドレス空間にある限り (特に、新しいデータも同じメモリ ページに収まるなどの理由で同じメモリ ページにある場合)、アクセス中にプログラムがクラッシュすることはありません。古いデータを取得するだけです。

より建設的な注意: 最大要素を事前に知っていれば、ソリューションは機能しますが、これは難しいかもしれません (来年 4k カメラを手に入れると考えてください ;-))。その場合、ところで、とにかく単純な静的配列を取ることができます。

おそらくstd::map、単純なベクトル listofA の代わりに、a を使用して A オブジェクトを格納することもできます。各 A オブジェクトには、マップへのキーとして使用する何らかの一意の ID (最も簡単なケースでは A の静的カウンター) が必要です。Bs は、As のアドレスではなくキーを格納します。

于 2016-02-05T14:15:57.943 に答える
0

ネットワークの構築方法に間違いがなければ、問題ありません。それを評価するには、さらにコードを投稿する必要があります。また、メンバーを再割り当てすると、それらを指すすべてのポインターが無効になるため、いずれかのベクトルを変更した後は、いずれのベクトルも使用できません。しかし、管理対象オブジェクトへの生のポインタを使用することは、ネットワークを構築する正しい方法です。

管理対象オブジェクトとは、有効期間がネットワークよりも長く続くことが保証され、メモリが自動的に解放されるオブジェクトを意味します。したがって、それらは、ある種のスマート ポインターによって管理されるコンテナーまたはオブジェクトの要素である必要があります。

ただし、ハードウェアに問題があるようです。

于 2016-02-05T13:53:15.993 に答える