[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Segmentation Fault Blues...
From: |
bleydorf |
Subject: |
Segmentation Fault Blues... |
Date: |
Thu, 21 Aug 1997 16:11:39 -0400 |
Hi,
(Background info: The "simple" simulation I am attempting to create is
called Problems, Problems are agents which will scury around a "world"
looking for solutions(also agents). For now, the problems (and
solutions) are assigned a random integer, and then the problems look for
solutions which are nearest to their value.)
But, I haven't gotten that far yet, I took heatbugs, and "converted" it
to the problems simulation. At first, I created both problem agents,
solution agents, the Neighborhood (which I realized I didnt need), and
the model and observer swarms. After I got the "segmentation fault"
error, yesterday, in an effort to remove all "unnecessary" code, so I
took out all stuff dealing with the solution agents and the neighborhood
stuff.
As the code exists now, all it "should" do, is create the Problem
agents, in a world much like heatbugs, and then the agents should move
randomly. But, now when I hit, "GO" it returns a "segmentation fault
error".
As Ted suggested yesterday, I attempted to use gdb to debug it, but
(either I didnt know how to use gdb, or it didnt like it), so that
didn't seem to work.
So, I have enclosed my "simplified code" as well as the makefile I used,
if anyone has a couple minutes could they look over it, and tell me if
it looks OK. For the life of me, I've really hit a "WALL". If anyone
wants to give me a quick tutorial on gdb, or how I could use gdb to
diagnose this problem I would also appreciate it.
Thanks,
Brad.
ps. Code follows:
> The following is the simplified version of the Problem simulation, at the
> beginning of each file, there will
> be a "//" describing which file it is.
>
> //Makefile
>
> SWARMHOME=/usr/src/swarm-1.0.2
> APPLICATION=problems
> OBJECTS=Problem.o main.o ProblemModel.o ProblemObserver.o
> APPLIBS=-lspace
> OTHERCLEAN=
>
> include $(SWARMHOME)/Makefile.appl
>
>
> main.o: main.m Problem.h ProblemObserver.h
> Problem.o: Problem.m Problem.h
> ProblemObserver.o: ProblemObserver.m ProblemObserver.h ProblemModel.h
> ProblemModel.o: ProblemModel.m ProblemModel.h
>
>
>
> // main.m
>
> #import <simtools.h> // ... for initSwarm() and swarmGUIMode
> #import "ProblemObserver.h"
>
> int
> main(int argc, char ** argv) {
> id theTopLevelSwarm ;
>
> initSwarm(argc, argv);
> theTopLevelSwarm = [ProblemObserver create: globalZone];
>
> [theTopLevelSwarm buildObjects];
> [theTopLevelSwarm buildActions];
> [theTopLevelSwarm activateIn: nil];
> [theTopLevelSwarm go];
>
> // theTopLevelSwarm has finished processing, so it's time to quit.
> return 0;
> }
>
>
>
> // Problem.h (Heatbug.h)
>
> #import <space.h> // we use Space features
> #import <tkobjc/Raster.h> // special class for graphics
>
> // The definition of a Problem object. We inherit code from the generic
> // SwarmObject, which provides memory allocation and other niceties. It
> // does not provide any sort of agent behaviour, though, that's up to us.
> // First, heatbugs have a lot of state variables:
>
> @interface Problem: SwarmObject {
>
> int idealNumber;
> int x, y; // my spatial coordinates
> float problemRandomMoveProb; // chance of moving
> randomly
>
> Grid2d * world; // the world I live in
> int worldXSize, worldYSize; // how big that world is
> Color problemColor; // my colour (display)
> id problemPixmap; // my pixmap (display)
> }
>
> // these methods are used to initialize the object's state. First,
> // methods that have to be sent to create an object.
>
> -setWorld: (Grid2d *) w; // which world are we in?
>
> // As a convention, we put the -createEnd here to indicate that we're done
> // defining new methods that are required before createEnd.
>
> -createEnd;
>
> // Other methods to set Heatbug state. These can be called after the
> // object has been fully created.
>
> -setIdealNumber: (int) i;
> -setRandomMoveProbability: (float) p;
> -setX: (int) x Y: (int) y; // problem's position
> -setProblemColor: (Color) c; // problem's colour (display)
> -setPixmap: pm; // problem's pixmap (display)
>
> // The major problem behavior: do one "time step".
>
> -step;
>
> // extra display code (problems currently draw themselves)
>
> -drawSelfOn: (Raster *) r;
>
> @end
>
>
> // Problem.m (Heatbug.m)
>
> #import "Problem.h"
> #import <simtools.h>
>
> // Defining the methods for a Problem.
>
> @implementation Problem
>
> // Initialize crucial state for the heatbug.
>
> -setWorld: (Grid2d *) w {
>
> // Strictly speaking, this check isn't necessary. But we intend these
> // parameters to be immutable once set, so to be extrasafe we check:
> // it could catch an error later.
>
> if (world != nil) {
> [InvalidArgument raiseEvent: "You can only set the world of a problem at
> once at creation time\n"];
> }
> world = w;
>
> return self;
> }
>
> // createEnd. This is a good place to put code that does various sorts
> // of initialization that can only be done after some parameters of the
> // object are set. It's also a good time to check for errors in creation.
>
> -createEnd {
>
> // make sure the user set up world.
>
> if (world == nil) {
> [InvalidCombination raiseEvent: "Problem was created without a world.\n"];
> }
>
> // Cache the worldSize for speed of later access.
>
> worldXSize = [world getSizeX];
> worldYSize = [world getSizeY];
>
> return self; // CRUCIAL!
> }
>
> // Simple set methods for Problem state.
>
> -setIdealNumber: (int) i {
> idealNumber = i;
> return self;
> }
>
> -setRandomMoveProbability: (float) p {
> randomMoveProbability = (float) p;
> return self;
> }
>
> // This method is a bit dangerous: we blindly put ourselves on top of
> // the grid no matter what's underneath us: because Grid2d only allows
> // one object per square, we could be destroying data.
>
> -setX: (int) inX Y: (int) inY {
> x = inX;
> y = inY;
> [world putObject: self atX: x Y: y]; // yikes!
> return self;
> }
>
> // All of the previous code is basic Swarm object programming. The
> // real simulation code follows.
>
> // Problem behaviour is actually implemented here. The notion of a "step"
> // method is a nice simplification for basic simulations.
>
> -step {
> int newX, newY;
> int tries;
>
> // update my current unhappiness value: abs(ideal - here);
>
> if (((float)[uniformDblRand
> getDoubleWithMin: 0.0 withMax: 1.0]) < randomMoveProbability) {
>
> newX = (x +
> [uniformIntRand
> getIntegerWithMin: -1L withMax: 1L]); // pick a random spot
>
> newY = (y + [uniformIntRand getIntegerWithMin: -1L withMax: 1L]);
>
> newX = (newX + worldXSize) % worldXSize; // normalize coords
> newY = (newY + worldYSize) % worldYSize;
> }
>
> // Part of the heatbug simulation is that two bugs cannot be in the
> // same spot. The code to enforce that is done here: ...
>
> tries = 0;
> while ([world getObjectAtX: newX Y: newY] != nil && tries < 10) {
> newX = (x + [uniformIntRand getIntegerWithMin: -1L withMax: 1L] +
> worldXSize) % worldXSize;
> newY = (y + [uniformIntRand getIntegerWithMin: -1L withMax: 1L] +
> worldYSize) % worldYSize;
>
> tries++; // don't try too hard.
> }
> if (tries == 10) { // no nearby clear spot
> newX = x; // so just don't move.
> newY = y;
> }
>
> // Ok, we've found a spot to move to...
> // Now move ourselves in the grid and update our coordinates.
>
> [world putObject: nil atX: x Y: y];
> x = newX;
> y = newY;
> [world putObject: self atX: newX Y: newY];
>
> // all done moving! Return self.
>
> return self;
> }
>
> // Extra bits of display code: setting our colour, drawing on a window.
> // This code works, but it'd be better if there were a generic object
> // that knew how to draw agents on grids.
>
> -setProblemColor: (Color) c {
> problemColor = c;
> return self;
> }
>
> -setPixmap: pm {
> problemPixmap = pm;
> return self;
> }
>
> -drawSelfOn: (Raster *) r {
> [r draw: problemPixmap X: x Y: y];
> return self;
> }
>
> @end
>
>
> // ProblemModelSwarm.h
>
> #import "Problem.h"
> #import <space.h>
> #import <activity.h>
> #import <collections.h>
> #import <swarmobject/Swarm.h>
> #import <tkobjc.h>
> #import <swarmobject.h>
>
> @interface ProblemModel : Swarm {
>
> int numProblems; // simulation parameters
> int worldXSize, worldYSize;
> int minIdealNumber, maxIdealNumber;
> double problemRandomMoveProb;
>
> id modelActions; // scheduling data structures
> id modelSchedule;
>
> id problemList; // list of all the problems
> Grid2d * world; // The neighborhood
> XPixmap *problemPixmap; // problem's pixmap
>
> }
>
> -getProblemList; // access methods
> into the
>
> -(Grid2d *) getWorld; // model swarm. These methods
> // allow the model
> swarm to
> // be observed.
>
> +createBegin: (id) aZone; // extra methods you
> -createEnd; // provide for Swarms
> -buildObjects;
> -buildActions;
> -activateIn: (id) swarmContext;
>
> @end
>
>
>
> //ProblemModelSwarm.m
>
> #import "ProblemModel.h"
> #import <simtools.h>
>
> @implementation ProblemModel
>
> // These methods provide access to the objects inside the ModelSwarm.
> // These objects are the ones visible to other classes via message call.
> // In theory we could just let other objects use Probes to read our state,
> // but message access is frequently more problemvenient.
>
> -getProblemList {
> return problemList;
> }
>
> -getWorld {
> return world;
> }
>
>
> // createBegin: here we set up the default simulation parameters.
>
> +createBegin: (id) aZone {
> ProblemModel * obj;
> ProbeMap * probeMap;
>
> // First, call our superclass createBegin - the return value is the
> // allocated ProblemModel object.
>
> obj = [super createBegin: aZone];
>
> // Now fill in various simulation parameters with default values.
>
> obj->numProblems = 50;
> obj->worldXSize = 80;
> obj->worldYSize = 80;
> obj->minIdealNumber = 1;
> obj->maxIdealNumber = 50;
> obj->problemRandomMoveProb = 0.9;
>
> // And build a customized probe map. Without a probe map, the default
> // is to show all variables and messages. Here we choose to
> // customize the appearance of the probe, give a nicer interface.
>
> probeMap = [EmptyProbeMap createBegin: aZone];
> [probeMap setProbedClass: [self class]];
> probeMap = [probeMap createEnd];
>
> // Add in a bunch of variables, one per simulation parameter
>
> [probeMap addProbe: [probeLibrary getProbeForVariable: "worldXSize"
> inClass: [self class]]];
> [probeMap addProbe: [probeLibrary getProbeForVariable: "worldYSize"
> inClass: [self class]]];
> [probeMap addProbe: [probeLibrary getProbeForVariable: "numProblems"
> inClass: [self class]]];
> [probeMap addProbe: [probeLibrary getProbeForVariable:
> "problemRandomMoveProb"
> inClass: [self class]]];
> [probeMap addProbe: [probeLibrary getProbeForVariable: "minIdealNumber"
> inClass: [self class]]];
> [probeMap addProbe: [probeLibrary getProbeForVariable: "maxIdealNumber"
> inClass: [self class]]];
>
> // Now install our custom probeMap into the probeLibrary.
>
> [probeLibrary setProbeMap: probeMap For: [self class]];
>
> return obj;
> }
>
> // createEnd: we could create some objects here if we knew we needed
> // them. But this method is called before the user is allowed to fill
> // in any customization of the model, so we defer most object creation
> // to later. (In this example, this method does nothing at all and could
> // just be inherited. But it's here to show you a place to customize.)
>
> -createEnd {
> return [super createEnd];
> }
>
> // Now it's time to build the model objects. We use various parameters
> // inside ourselves to choose how to create things.
>
> -buildObjects {
> int i;
>
> // allow our parent class to build anything.
>
> [super buildObjects];
>
> // First, set up objects used to represent the environment.
> // Set up the grid used to represent agent position
>
> world = [Grid2d createBegin: [self getZone]];
> [world setSizeX: worldXSize Y: worldYSize];
> world = [world createEnd];
>
> problemPixmap = [XPixmap createBegin: [self getZone]];
> [problemPixmap setFile: "problem.xpm"];
> problemPixmap = [problemPixmap createEnd];
>
> // Create a list to keep track of the agents in the model.
>
> problemList = [List create: [self getZone]];
>
> // Create agents themselves. This is a fairly complex step, as is
> // appropriate: the agents are essential aspects of the simulation.
>
> // First, a quick hack. During creation we might put several agents
> // in the same square. This is a design flaw, but it's one that's not
> // fatal, so we ask the world object not to warn us about it. This is
> // not an example to be emulated :-)
>
> [world setOverwriteWarnings: 0];
>
> // Now a loop to create a bunch of problems.
>
> for (i = 0; i < numProblems; i++) {
> Problem * problem;
> int idealNumber;
>
> // Choose a random ideal number from the specified
> // range (model parameters).
>
> idealNumber = [uniformIntRand
> getIntegerWithMin: minIdealNumber withMax: maxIdealNumber];
>
> // Create the problem, set the creation time variables
>
> problem = [Problem createBegin: [self getZone]];
> [problem setWorld: world];
> problem = [problem createEnd];
>
> // Add the problem to the end of the list.
>
> [problemList addLast: problem];
>
> // Now initialize the rest of the heatbug's state.
>
> [problem setPixmap: problemPixmap];
> [problem setIdealNumber: idealNumber];
>
> [problem setX: [uniformIntRand
> getIntegerWithMin: 0L
> withMax: (worldXSize-1)] // random position
> Y: [uniformIntRand getIntegerWithMin: 0L withMax: (worldYSize-1)]];
> }
>
> [world setOverwriteWarnings: 1]; // ok, done cheating.
>
> return self;
> }
>
> // Here is where the model schedule is built, the data structures
> // that define the simulation of time in the mode. The core is an
> // actionGroup that has a list of actions. That's then put in a Schedule.
>
> -buildActions {
>
> [super buildActions];
>
> // Create the list of simulation actions.
>
> modelActions = [ActionGroup create: [self getZone]];
> [modelActions createActionForEach: problemList message: M(step)];
>
> // Then we create a schedule that executes the modelActions.
> // This is a simple schedule, with only one action that is just
> // repeated every time. See mousetraps for more complicated schedules.
>
> modelSchedule = [Schedule createBegin: [self getZone]];
> [modelSchedule setRepeatInterval: 1];
> modelSchedule = [modelSchedule createEnd];
> [modelSchedule at: 0 createAction: modelActions];
>
> return self;
> }
>
> // Now set up the model's activation. swarmContext indicates where
> // we're being started in - typically, this model is run as a subswarm
> // of an observer swarm.
>
> -activateIn: (id) swarmContext {
>
> // First, activate ourselves via the superclass activateIn: method.
> // Just pass along the problemtext: the activity library does the right
> thing.
>
> [super activateIn: swarmContext];
>
> // Now activate our own schedule.
>
> [modelSchedule activateIn: self];
>
> // Finally, return our activity.
>
> return [self getActivity];
> }
>
> @end
>
>
>
> //ProblemObserverSwarm.h
>
> #import <swarmobject.h>
> #import <space.h>
> #import <activity.h>
> #import <tkobjc.h>
> #import <collections.h>
> #import <simtools.h>
> #import <analysis.h>
> #import "ProblemModel.h"
>
> @interface ProblemObserver : GUISwarm {
> int displayFrequency; // one parameter:
> update freq
>
> id displayActions; // schedule data structs
> id displaySchedule;
>
> ProblemModel * problemModel; // the Swarm we're observing
>
> // Lots of display objects. First, widgets
>
> XColormap * colormap; // allocate colours
> ZoomRaster * worldRaster; // 2d display widget
>
> // Now, higher order display and data objects
>
>
> Object2dDisplay * problemDisplay; // display the problems
> }
>
> // Methods overriden to make the Swarm.
>
> +createBegin: (id) aZone;
> -createEnd;
> -buildObjects;
> -buildActions;
> -activateIn: (id) swarmContext;
>
> @end
>
>
>
> //ProblemObserverSwarm.m
>
> #import "ProblemObserver.h"
> #import "ProblemModel.h"
> #import <collections.h>
> #import <swarmobject.h>
> #import <analysis.h>
>
> @implementation ProblemObserver
>
> // createBegin: here we set up the default observation parameters.
>
> +createBegin: (id) aZone {
> ProblemObserver * obj;
> ProbeMap * probeMap;
>
> // Superclass createBegin to allocate ourselves.
>
> obj = [super createBegin: aZone];
>
> // Fill in the relevant parameters (only one, in this case).
>
> obj->displayFrequency = 1;
>
> // Also, build a customized probe map. Without a probe map, the default
> // is to show all variables and messages. Here we choose to
> // customize the appearance of the probe, give a nicer interface.
>
> probeMap = [EmptyProbeMap createBegin: aZone];
> [probeMap setProbedClass: [self class]];
> probeMap = [probeMap createEnd];
>
> // Add in a bunch of variables, one per simulation parameters
>
> [probeMap addProbe: [probeLibrary getProbeForVariable: "displayFrequency"
> inClass: [self class]]];
>
> // Now install our custom probeMap into the probeLibrary.
>
> [probeLibrary setProbeMap: probeMap For: [self class]];
>
> return obj;
> }
>
> // createEnd: create objects we know we'll need. In this case, none,
> // but you might want to override this.
>
> -createEnd {
> return [super createEnd];
> }
>
> // Create the objects used in the display of the model. This code is
> // fairly complicated because we build a fair number of widgets. It's
> // also a good example of how to use the display code.
>
> -buildObjects {
> id modelZone; // zone for model.
> int i;
>
> [super buildObjects];
>
> // First, we create the model that we're actually observing. The
> // model is a subswarm of the observer. We also create the model in
> // its own zone, so storage is segregated.
>
> modelZone = [Zone create: [self getZone]];
> problemModel = [ProblemModel create: modelZone];
>
> // Now create probe objects on the model and ourselves. This gives a
> // simple user interface to let the user change parameters.
>
> [probeDisplayManager createProbeDisplayFor: problemModel];
> [probeDisplayManager createProbeDisplayFor: self];
>
> // Instruct the control panel to wait for a button event: we halt here
> // until someone hits a control panel button so the user can get a
> // chance to fill in parameters before the simulation runs
>
> [controlPanel setStateStopped];
>
> // OK - the user has specified all the parameters for the simulation.
> // Now we're ready to start.
>
> // First, let the model swarm build its objects.
>
> [problemModel buildObjects];
>
> // Now get down to building our own display objects.
>
> // First, create a colormap: this is a global resource, the information
> // here is used by lots of different objects.
>
> colormap = [XColormap create: [self getZone]];
>
> // Colours [0,64) are assigned to the range Red [0, 1), for heat display.
>
> for (i = 0; i < 64; i++)
> [colormap setColor: i ToRed: 0 Green: (double)i /63.00 Blue: 0];
>
> // Colour 64 is set to green, to display heatbugs
>
> [colormap setColor: 64 ToName: "red"];
>
> // Colour 65 is set to white, used in this case below on probed heatbug.
>
> [colormap setColor: 65 ToName: "white"];
>
> // Now go in to the heatbugs in the model and set their colours to green
> (64)
>
> [[problemModel getProblemList] forEach:
> M(setProblemColor:) : (void *) 64];
>
> // Next, create a 2d window for display, set its size, zoom factor, title.
>
> worldRaster = [ZoomRaster create: [self getZone]];
> [worldRaster setColormap: colormap];
> [worldRaster setZoomFactor: 4];
> [worldRaster setWidth: [[problemModel getWorld] getSizeX]
> Height: [[problemModel getWorld] getSizeY]];
> [worldRaster setWindowTitle: "The Neighborhood"];
> [worldRaster pack]; // draw the window.
>
> // And also create an Object2dDisplay: this object draws heatbugs on
> // the worldRaster widget for us, and also receives probes.
>
> problemDisplay = [Object2dDisplay createBegin: [self getZone]];
> [problemDisplay setDisplayWidget: worldRaster];
> [problemDisplay setDiscrete2dToDisplay: [problemModel getWorld]];
> [problemDisplay setObjectCollection: [problemModel getProblemList]];
> [problemDisplay setDisplayMessage: M(drawSelfOn:)]; // draw method
> problemDisplay = [problemDisplay createEnd];
>
> // Also, tell the world raster to send mouse clicks to the problemDisplay
> // this allows the user to right-click on the display to probe the bugs.
>
> [worldRaster setButton: ButtonRight Client: problemDisplay Message:
> M(makeProbeAtX:Y:)];
>
> return self;
> }
>
> // Create the actions necessary for the simulation. This is where
> // the schedule is built (but not run!)
>
> -buildActions {
> [super buildActions];
>
> // First, let our model swarm build its own schedule.
>
> [problemModel buildActions];
>
> // Create an ActionGroup for display: a bunch of things that occur in
> // a specific order, but at one step of simulation time. Some of these
> // actions could be executed in parallel, but we don't explicitly
> // notate that here.
>
> displayActions = [ActionGroup create: [self getZone]];
>
> // Schedule up the methods to draw the display of the world
>
> [displayActions createActionTo: problemDisplay message: M(display)];
> [displayActions createActionTo: worldRaster message: M(drawSelf)];
>
> // Schedule the update of the probe displays
>
> [displayActions createActionTo: probeDisplayManager message: M(update)];
>
> // Finally, schedule an update for the whole user interface code.
> // This is crucial: without this, no graphics update and the control
> // panel will be dead. It's best to put it at the end of the display
> schedule
>
> [displayActions createActionTo: controlPanel message: M(doTkEvents)];
>
> // And the display schedule. Note the repeat interval is set from our
> // own Swarm data structure. Display is frequently the slowest part of a
> // simulation, so redrawing less frequently can be a help.
>
> displaySchedule = [Schedule createBegin: [self getZone]];
> [displaySchedule setRepeatInterval: displayFrequency]; // note frequency!
> displaySchedule = [displaySchedule createEnd];
> [displaySchedule at: 0 createAction: displayActions];
>
> return self;
> }
>
> // activateIn: - activate the schedules so they're ready to run.
> // The swarmContext argument has to do with what we were activated *in*.
> // Typically the ObserverSwarm is the top-level Swarm, so it's activated
> // in "nil". But other Swarms and Schedules and such will be activated
> // inside of us.
>
> -activateIn: (id) swarmContext {
>
> // First, activate ourselves (just pass along the context).
>
> [super activateIn: swarmContext];
>
> // Activate the model swarm in ourselves. The model swarm is a
> // subswarm of the observer swarm.
>
> [problemModel activateIn: self];
>
> // Now activate our schedule in ourselves. This arranges for the
> // execution of the schedule we built.
>
> [displaySchedule activateIn: self];
>
> // Activate returns the swarm activity - the thing that's ready to run.
>
> return [self getActivity];
> }
>
> @end
==================================
Swarm-Support is for discussion of the technical details of the day
to day usage of Swarm. For list administration needs (esp.
[un]subscribing), please send a message to <address@hidden>
with "help" in the body of the message.
==================================
- Segmentation Fault Blues...,
bleydorf <=