2

実行中にさまざまな奇妙なメモリ破損で失敗するコードがあります。コードのこのセクションに絞り込みました。

List<CollisionBlock> WorldClient::getCollisionBlocks(RectF const& boundBox, bool doSort, Vec2F sortCenter) const {
  auto res = m_collisionGenerator.getPolys(boundBox);

  if (doSort) {
    sort(res, [=](CollisionBlock const& block1, CollisionBlock const& block2) {
    return magSquared(sortCenter - block1.poly.center()) < magSquared(sortCenter - block2.poly.center());
      });
  }

  return res;
}

const&ラムダからを削除すると、コードは正常に機能します。どうしてか分かりません。コンパイラのバグに遭遇したのか、それとも私が見落としている明らかな何かがあるのか​​と思っていました。

CollisionBlockの定義は次のとおりです。

struct CollisionBlock {
  PolyF poly;
  // Will never be None
  CollisionKind kind;
  // Normalzied vector encoding the slope of the block we collided with.
  // Always faces right, y component can be positive or negative.
  Vec2F slope;
};

Linux 32ビット(g ++バージョン4.7.0および4.6.3)、MacOSX(ワードサイズとg ++バージョンが不明)、Windows 7 64ビット(g ++バージョン4.6.3)、Windows 7 32ビット(g ++)で再現できます。バージョン4.6.2および4.6.3)、ただしLinux 64ビット(g ++バージョン4.6.1)ではありません。

ブーストではなく、C++11を使用しています。

Poly::center()

Coord center() const {
  return sum(m_vertexes) / (DataType)m_vertexes.size();
}

sum

template<typename Container>
typename Container::value_type sum(Container const& cont) {
  return reduce(cont, std::plus<typename Container::value_type>());
}

reduce

// Somewhat nicer form of std::accumulate
template<typename Container, typename Function>
typename Container::value_type reduce(Container const& l, Function f) {
  typename Container::const_iterator i = l.begin();
  typename Container::value_type res{};

  if (i == l.end())
    return res;

  res = *i++;
  while (i != l.end())
    res = f(res, *i++);
  return res;
}       

sort

template<typename Container, typename Compare>
void sort(Container& c, Compare comp) {
  std::sort(c.begin(), c.end(), comp);
}

この質問にはかなりのことが起こっています。申し訳ありませんが、より小さなテストケースを作成してみます。

アップデート:

の呼び出しをsumに置き換えても効果はPoly::centerありstd::accumulateません。

4

4 に答える 4

1

エラーはあなたが投稿したコードの範囲外であると私はかなり確信しています。以下の私のダミーコードを取得して、問題が発生し始めるまでゆっくりと実際のコードに変形することができます。見つけたら教えてください、とても興味があります。

参考までに、私はあなたがしていることに近づくためにいくつかの場所でコードを作成しなければなりませんでした。これが実際に行うのは、投稿したコードのほんの一部を実行することだけです。

#include <list>
#include <deque>
#include <vector>
#include <algorithm>

typedef double mocish;

typedef int CollisionKind; //is actually enum class
typedef mocish RectF;

class Vec2F {
public:
  Vec2F() {
    vertexes.push_back(0);
    vertexes.push_back(0);
  }
  Vec2F(float a, float b) {
    vertexes.push_back(a);
    vertexes.push_back(b);
  }

  float operator[](unsigned index) const {
    return vertexes[index];
  }

  float operator[](unsigned index) {
    return vertexes[index];
  }

  Vec2F operator+(Vec2F const& other) const {
    return Vec2F(vertexes[0]+other[0], vertexes[1]+other[1]);
  }

  Vec2F operator-(Vec2F const& other) const {
    return Vec2F(vertexes[0]-other[0], vertexes[1]-other[1]);
  }

  Vec2F operator*(float other) const {
    return Vec2F(vertexes[0]*other, vertexes[1]*other);
  }

  Vec2F operator/(float other) const {
    return Vec2F(vertexes[0]/other, vertexes[1]/other);
  }

  Vec2F operator=(Vec2F const& other) {
    vertexes[0] = other[0];
    vertexes[1] = other[1];
    return *this;
  }

private:
  std::deque<float> vertexes;
};

float magSquared(Vec2F const& a) {
  return a[0]*a[0]+a[1]*a[1];
}

typedef Vec2F Coord;

// Somewhat nicer form of std::accumulate
template<typename Container, typename Function>
typename Container::value_type reduce(Container const& l, Function f) {
  typename Container::const_iterator i = l.begin();
  typename Container::value_type res{};

  if (i == l.end())
    return res;

  res = *i++;
  while (i != l.end())
    res = f(res, *i++);
  return res;
}     


template<typename Container>
typename Container::value_type sum(Container const& cont) {
  return reduce(cont, std::plus<typename Container::value_type>());
}


struct PolyF
{
    PolyF()
    {
        m_vertexes.resize(4);
        std::generate( m_vertexes.begin(), m_vertexes.end(), [](){ return Vec2F(std::rand(), std::rand());} );
    }

    std::vector<Coord> m_vertexes;

    Coord center() const 
    {
      return sum(m_vertexes) / (float)m_vertexes.size();
    }
};

struct CollisionBlock 
{
  PolyF poly;
  // Will never be None
  CollisionKind kind;
  // Normalzied vector encoding the slope of the block we collided with.
  // Always faces right, y component can be positive or negative.
  Vec2F slope;
};


template<typename Container, typename Compare>
void sort(Container& c, Compare comp) {
  std::sort(c.begin(), c.end(), comp);
} 

struct CollisionGen
{
    std::deque<CollisionBlock> getPolys( RectF const& ) const
    {
        std::deque<CollisionBlock> collision_block_moc(50);
        return collision_block_moc;
    }
};

struct WorldClient
{
    CollisionGen m_collisionGenerator;


    std::deque<CollisionBlock> getCollisionBlocks(RectF const& boundBox, bool doSort, Vec2F sortCenter) const 
    {
      auto res = m_collisionGenerator.getPolys(boundBox);

    //auto test = magSquared(sortCenter - res.front().poly.center()) < magSquared(sortCenter - res.front().poly.center());

      if (doSort) {
        sort(res, [=](CollisionBlock const& block1, CollisionBlock const& block2) {
        return magSquared(sortCenter - block1.poly.center()) < magSquared(sortCenter - block2.poly.center());
          });
      }

      return res;
    }
};

    int main() 
    {
        WorldClient wc;
        while (true) {
          wc.getCollisionBlocks( 42.0, true, {0,0} );
        }
    }
于 2012-06-29T06:58:05.580 に答える
0

コンパレータは厳密な弱順序ですか?入力を一貫して順序付けていますか?で実際にゼロ初期化resしていないのではないかreduceと思うので、center()ゴミを返すことになります。これは一般的に簡単に確認できるはずです。resassert(f(res,res) == res)の宣言の直後に権利を追加してください。

コンパレータが一貫していない場合、を使用して未定義の動作に遭遇し、std::sort簡単にクラッシュする可能性があります。また、プラットフォーム、最適化などに注意してください。

于 2012-06-29T06:59:24.080 に答える
0

私の推測では、テンプレート List<> の反復子は、std::sort が必要とするランダム アクセス反復子ではありません。std::list は双方向反復のみを提供することに注意してください。

独自のリストを実装している場合は、反復子の実装を精査して、それが正しいこと、およびランダム アクセス反復子の概念の完全で正しい実装を提供していることを確認することをお勧めします。

于 2012-06-29T06:10:30.983 に答える
0

[=] と言って、参照を使用してラムダに値渡ししていることに気付きました。それを変更するか、 std::ref を使用して値を渡して、インスタンス自体への意図した参照を実際に使用する必要があります。

于 2012-06-29T06:21:12.233 に答える