4

我有一个相当大的 c++ 程序,包括一个“字符”类。在“Character.h”中,首先声明 struct CharacterSettings,然后声明类 Character(包括它们的构造函数)。

Character 具有(除其他外) CharacterSettings* 设置和 Point pos。CharacterSettings 有一个 Point preferredVelocity。

这工作正常。

但是,当我将任何公共变量添加到 Character 时,程序会在我调用它时崩溃:

drawLine(character.pos, character.pos+character.settings->preferredVelocity, character.radius/3.0, 128, 80, 0);

程序在这一行崩溃:

Point operator + (const Point &p2) const
    { return Point(x + p2.x, y + p2.y); }

我假设它正在尝试执行 character.pos+character.settings->preferredVelocity。我得到的错误信息是

Unhandled exception at 0x004bc4fc in ECMCrowdSimulation.exe: 0xC0000005: Access violation reading location 0x7f80000f.

当我查看它时, p2.x 和 p2.y 是未定义的。没有额外的变量,它们不是。我完全不知道发生了什么,甚至不知道如何开始调试,也不知道您需要什么信息来帮助我!任何帮助将不胜感激!

编辑:这里至少是 Character.h 文件!

#pragma once

/* 
 * ECM navigation mesh / crowd simulation software
 * (c) Roland Geraerts and Wouter van Toll, Utrecht University.  
 * ---
 * Character: A single moving character in the simulation.
*/

#include "../ECM/GraphComponents/CMNode.h"
#include "VectorOperation.h"
#include "IndicativeRoute.h"
#include "float.h"

#define _USE_MATH_DEFINES
#include <math.h>

#include <vector>
using std::vector;
#include <queue>
using std::queue;

#define CHARACTER_RELAXATIONTIME 0.5f

typedef vector<CMNode>::iterator node_ptr;
class Corridor;
class CMMResult;

    struct CMEdge;
    class CMMInterface;
    class MicroInterface;
    class CMMSceneTransfer;

    struct CharacterSettings
    {
    private:
        bool index_bb_initialized, index_bb_cp_initialized, index_ir_circle_initialized, index_ir_circle_mu_initialized;
        bool index_2nd_ir_circle_initialized, index_2nd_ir_circle_mu_initialized;

    public:
        // --- Unique identifier within the simulation
        int id;

        // --- Velocity and speed
        Point preferredVelocity;// Newly computed velocity *before* local collision avoidance
        Point newVelocity;      // Newly computed velocity (+ collision avoidance), to be applied in the "next" simulation step

        float total_max_speed;  // Maximum possible speed throughout the entire simulation
        float max_speed;        // Maximum speed at this point in time
        float min_desired_speed;// Minimum speed that the character tries to reach when it is not standing still

        Point lastAttractionPoint;

        // --- IRM parameters
        CMMInterface* cmmImplementation; // the type of indicative route to follow within the corridor, e.g. "shortest path" or "weighted side".
        // Only used in WEIGHTED_SIDE:
        float sidePreference;       // bias to following a certain "side" of the corridor. Must be between -1 (left) and 1 (right).
        float sidePreferenceNoise;  // extra noise factor that will be added to sidePreference at each route element.
        // Used in WEIGHTED_SIDE and SHORTEST_PATH
        float preferred_clearance;  // Distance (m) by which the agent prefers to stay away from obstacles.

        // --- Micro simulation model (e.g. for collision avoidance between characters)
        MicroInterface* microImplementation;// the local model to use
        short micro_maxNrNeighbours;        // the number of neighbours to check in the local model
        float micro_personalSpaceRadius;    // radius of the personal space (m), on top of the character's physical radius.
                                            // Entering this disk (radius + personalSpace) is seen as a 'collision'.

        // --- Corridor/Path pointers
        node_ptr index_bb;          // point on backbone path (used for computing attraction force)
        node_ptr index_bb_cp;       // point on the backbone path(used for computing the closest point)
        curve_ptr index_ir_circle;  // index to last point on the indicative route that intersects with a circle
        float index_ir_circle_mu;   // factor wrt to point on the indicative route that intersects with a circle

        friend Character; // only the Character class can look into private members (WvT: ugly C++ practice, but it does work)

        CharacterSettings(int _id, 
            // speed
            float _total_max_speed, float _min_desired_speed,
            // type of indicative route
            CMMInterface* _cmmImplementation, float _sidePreference, float _sidePreferenceNoise, float _clearance, 
            // type of micro simulation model
            MicroInterface* _microImplementation) :

            id(_id), total_max_speed(_total_max_speed), min_desired_speed(_min_desired_speed), 
            cmmImplementation(_cmmImplementation), sidePreference(_sidePreference), sidePreferenceNoise(_sidePreferenceNoise), preferred_clearance(_clearance),
            microImplementation(_microImplementation)
        {
            // velocities
            newVelocity = Point(0, 0);
            max_speed = total_max_speed;
            preferredVelocity = Point(0, 0);

            // corridor/IRM pointers
            index_bb_initialized = false;
            index_bb_cp_initialized = false;
            index_ir_circle_initialized = false;
            index_ir_circle_mu_initialized = false;

            // default micro settings
            micro_maxNrNeighbours = 5; // default for Karamouzas 2010: 5
            micro_personalSpaceRadius = 0.0f; // default for Karamouzas 2010: 0.5
        }
    };

    class Character
    {
    public:
        Point pos;
        float radius;
        Point prevPos;
        int i;    //The thing that is pretending to be the culprit, without this, it works fine.

        // goal data
        Point goalPos;
        float goalRadius;

        // status flags
        bool reachedGoal;
        bool freeze; // whether or not the character is temporarily frozen
        bool freezeNotified;
        bool reachedDestSet;

        Point velocity; // last used velocity

        // corridor/path pointers
        Point retraction, cp;

        //Contains more detailed settings of agent
        CharacterSettings * settings;

    public:
        // --- constructor
        Character(int _id, Point &_pos, float _radius, 
            // speeds
            float _total_max_speed, float _min_desired_speed,
            // type of indicative route
            CMMInterface* _cmmImplementation, float _sidePreference, float _sidePreferenceNoise, float _clearance,
            // type of micro simulation model
            MicroInterface* _microImplementation) :

            pos(_pos), radius(_radius) 
        {
            settings = new CharacterSettings(_id, _total_max_speed, _min_desired_speed, 
                _cmmImplementation, _sidePreference, _sidePreferenceNoise, _clearance, _microImplementation); 

            velocity = Point(0, 0);
            prevPos=_pos;

            reachedGoal = true;
            freeze = false;
            freezeNotified = false;
            reachedDestSet = false;
            //isProxy = false;
        }

        // --- destructor
        void removeSettings();

        // computing the new actual velocity through an acceleration vector: Euler integration
        inline void integrateEuler(const Point &acc, float dtSim)
        {                   
            settings->newVelocity = velocity + dtSim * acc;
            trim(settings->newVelocity, settings->max_speed);
        }

        inline void updatePos(float dtSim) 
        {       
            prevPos=pos;

            // update velocity
            velocity = settings->newVelocity;

            // update position
            pos += dtSim * velocity;

            // if the character is close to its goal, it should stop moving     
            if(!reachedGoal // goal was not already reached
                && settings->lastAttractionPoint == goalPos 
                && distSqr(pos, goalPos) < 0.25)//goalRadius)
            {   
                reachedGoal = true;
                // (do not reset the velocity, so that we can keep the last walking direction)
            }
        }

        void resetIndices();
        node_ptr &getIndex_bb(Corridor &corridor);
        node_ptr &getIndex_bb_cp(Corridor &corridor);
        curve_ptr &getIndex_ir_circle(IndicativeRoute &ir);
        float &getIndex_ir_circle_mu();
        Point &getRetraction() { return retraction; }
        Point &getClosestPoint() { return cp; }

        // computing the cost of some edge (in A*), by using personal preferences
        float getEdgeCost(const CMEdge& edge, float activeFraction);

        // computing the character's area, based on its radius
        float getArea() const;


    };

使一切崩溃的事情是添加 'int i' 。

4

1 回答 1

6

当使用旧版本头文件编译的文件与使用新版本编译的头文件链接时,通常会发生类似这样的奇怪问题。在这种情况下,两个文件之间的对象布局可能不同(至少,它sizeof是不同的)。

因此,在一个文件中,对象的所有内容可能看起来都是正确的,但是一旦传递给另一个文件中的函数,您就会得到完全随机的行为。

在这种情况下,重建整个项目可以解决问题。更好的是,如果您手动编写 Makefile,请尝试修复依赖关系。如果你使用 gcc/g++,你可以使用这样的命令来生成 Makefile 可接受的依赖:

g++ -MM -MG -Ipath/to/includes/that/should/be/part/of/dependency *.cpp
于 2012-07-31T12:41:26.007 回答