I7: Relations crash Dynamic Objects Extension or vice-versa

I’ve run into a bad problem involving an interplay between either the Dynamic Tables or Dynamic Objects extensions for Inform 7 and user-defined relations. Basically the problem is that if a sufficient number of objects exist in the game world, and a relation could possibly hold between them (even though said relation does not in fact hold), then Inform 7 crashes when a new object is dynamically created using the Dynamic Objects extension. Whether the trouble is with Dynamic Objects, or rather with Dynamic Tables (which is required to run the former), or rather with my own code, I can’t say (the extensions themselves are both written in Inform 6 code, which I am not really able to comprehend). There was no contact info for the author of the extensions in the accompanying documentation, and my preliminary on-line research didn’t turn up any discussion of this issue anywhere. I was hoping that someone here might be familiar with the extensions and how Inform 7 allocates or uses memory.

I only recently started using the Dynamic Objects/Tables extension to solve a few problems in a sub-project that is part of a larger ruleset I’ve been working on. Everything was working fine until I integrated the sub-project into my main project, and immediately Inform 7 began to crash each time something was created per the Dynamic Objects process. After some experimenting, I discovered that a potentially large but in practice hardly-used relation defined in my main project was not getting along with either Dynamic Objects or Dynamic Tables. However, I don’t understand enough about how Inform 7 uses memory to really comprehend the true nature of the problem, except to say that the problem definitely seems to be some sort of memory issue.

In my main project, I have several actions where a new object is dynamically created. The process seems to finish, and report rules associated with it appear in the test game; then a very large number of error messages that say:

[** Programming error: tried to read outside memory using → **]

start running down the screen and Inform crashes (a true crash, i.e. “Inform 7 caused a stack fault in module Inform7.exe”). For example, I have an action where the player pours some water from a full cup into an empty cup, requiring the creation of a new bit of water in the empty cup. So in my test game, I see:

pour pitcher in mug
You pour some water from the pitcher into the mug.

[** Programming error: tried to read outside memory using → ]
[
Programming error: tried to read outside memory using → ]
[
Programming error: tried to read outside memory using → **]

repeated a few dozen times, after which Inform crashes.

I set out to see if I could construct a small test scenario that would recreate the problem, which is shown below. I’m not looking for any particular tips or advice on the substance of the rather crude code posted below, since it’s only purpose is to simply demonstrate the issue that crashes Inform for me; what I really need help with is determining the cause and hopefully potential solutions to the more general crashing scenario.

First I wrote a quick scenario that would utilize creating objects dynamically. Note that if anyone would like to try this scenario for themselves they’ll need both the Dynamic Tables and Dynamic Objects extensions available from the Inform 7 website, and will have to set the project file to compile to Glulx. Furthermore, hopefully as a new person to the forum here I can be excused for not yet getting the hang of the “code-posting” function, as the tabs in the following code were converted to spaces (so you’ll have to set the tabs manually in Inform).

[code]Include Dynamic Objects by Jesse Mcgrew.

Use slow route-finding.

Rule for printing room description details: stop.

Rule for printing room description details of a container: omit contents in listing.

The testarea is a room. The description of the testarea is “A bare room that serves as your workshop.”.

A tissue is a kind of thing. The description of a tissue is usually “A [if the noun is clean]pristine[otherwise]used[end if] white paper tissue with a hint of a pleasant fragrance.”. A tissue can be clean or soiled. A tissue is usually clean.

A container called a box of tissues is in the testarea. The description of the box of tissues is “A shoebox-sized box of tissues emblazoned with a bright blue and white pattern. [if the box contains anything]A tissue is sticking out of the top of the box[otherwise]The box is empty[end if].”. The box of tissues is open and not openable. The box of tissues has a number called tissuecount. Tissuecount is usually 25.

One tissue is in the box of tissues.

After printing the name of the box of tissues while taking inventory: omit contents in listing.

A pencil is in the testarea. The description of the pencil is “A sharpened No.2 pencil, painted a dull yellow. A fine eraser is on one end.”.

An eraser is a kind of thing. The description of an eraser is usually “A rubber eraser, with plenty of life left in it.”.

One eraser is part of the pencil.

A container called the trash can is in the testarea. The description of the trash can is “A small brown plastic trash bin.”. The trash can is open and not openable.

Check inserting something into the box of tissues:
if the second noun contains a tissue and the noun is not a tissue:
say “The box is only for tissues.” instead;
if the noun is a tissue:
if the noun is soiled:
say “Your wife will be very upset if you do that. Use the trash can, you slob.” instead.

Does the player mean taking a tissue that is in the box of tissues: it is likely.

Instead of taking a tissue:
if the noun is in the box of tissues:
if the tissuecount of the box of tissues is less than 1:
say “There aren’t any more tissues. Looks like you’ll have to wipe your nose on your sleeve.”;
stop the action;
otherwise:
if the tissuecount of the box of tissues is at least 2:
let newtissue be a new object cloned from the noun;
move newtissue to the player;
decrease the tissuecount of the box of tissues by 1;
say “You pull a tissue from the box.”;
otherwise:
let abcd be a random tissue in the box of tissues;
now abcd is carried by the player;
decrease the tissuecount of the box of tissues by 1;
say “You take the last tissue from the box.”;
otherwise:
continue the action.

Connexion relates things to each other.

The verb to phylink (he phylinks, they phylink, he phylinked, it is phylinked, he is phylinking) implies the connexion relation.

Definition: a thing is linkedup if it phylinks anything.[/code]

I had determined that a relation called “connexion” in my main project, which is in practice rarely used (it is used to simulate the flow of electricity between power outlets, power cords, and electrical devices) was somehow directly related to Inform crashing during/after dynamically creating an object, which is why I tacked the seemingly out-of-place definition of the relation onto the end of the tissue-test case presented here. I was initially a bit frustrated when I ran the tissue-test scenario presented here and there were no problems.

get tissue
You pull a tissue from the box.

After playing around for a while, I noticed that in the Index pane of my main project, the connexion relation is shown as requiring 19K of memory, but in the Index pane of this test scenario it was not even listed as having a memory usage. I had a thought then that perhaps the number of objects in my main project which could potentially participate in the connexion relation (even though in practice only a handful of items do so) might have some bearing on the problem. So I started adding on to the end of the tissue-test scenario presented above:

[code]A marble is a kind of thing. The description of a marble is usually “A shiny marble.”.

The northern-testarea is north of the testarea.

There are 50 marbles in the northern-testarea.

The southern-testarea is south of the testarea.

There are 50 marbles in the southern-testarea.

The western-testarea is west of the testarea.

There are 50 marbles in the western-testarea.

The eastern-testarea is east of the testarea.

There are 50 marbles in the eastern-testarea.[/code]

At this point, I was rewarded with the crashing problem faithfully recreated:

get tissue
You pull a tissue from the box.

[** Programming error: tried to read outside memory using → ]
[
Programming error: tried to read outside memory using → ]
[
Programming error: tried to read outside memory using → **]

repeated a few dozen times, after which Inform crashed.

I’m hoping someone will be able to offer some guidance about what may be happening here. What is outside memory, what is trying to read it (or perhaps–read ‘outside’ of it), and what is said reader “using”?

If need be I can find some other way to duplicate the effect of the “connexion” relation in my main project without using any relations at all, and I am now firmly committed to the requirement of being able to create objects dynamically. However, neither of these considerations really address the larger issues here, namely:

a) I am doing something wrong in using any sort of relation modeled in the format of the connexion relation, or
b) is there a bug or other problem in either the Dynamic Tables or Dynamic Objects extensions themselves (and if so, whether anything can be done about it), or
c) all of the above.

Thanks in advance to anyone able to comment on this admittedly obscure issue.

Jesse McGrew is often to be found on rec.arts.int-fiction. If you post about this there, I’m pretty sure he’ll respond quickly.

FWIW, I copied your code and got exactly the same result, except that Inform (i.e., the Windows IDE) didn’t crash.

–JA

Thanks for verifying the “[** Programming error: tried to read outside memory using -> **]” aspect of the problem; actually that is more helpful to me than it one might initially think, as I seem to generally have some unusual troubles with Inform 7.

I don’t have any immediate means to post things to rec.arts.int-fiction (or any other newsgroup), but there’s no reason I couldn’t look into what would be required for me to do so.

I can see where the crashing aspect of the problem I talked about above (as distinct from the general relations vs. Dynamic Objects problem) could be a localized issue for me. I’m a little curious in fact whether anyone else has tried to use Inform 7 on a Windows 98 computer (beyond installing the program and doing an example or two from the documentation), and if so what your experience was. I’ve certainly had a lot of trouble with it in general; one of the Inform staff was extremely helpful and put a considerable amount of effort into getting the program to generally work for me, but I still have some functionality issues (of which the crash part of problem discussed above is likely another instance).

Endosphere, here are your immediate means for posting to rec.arts.int-fiction: groups.google.com/group/rec.arts … topics?lnk . :slight_smile:

Hi, Jesse McGrew here. I think I found the bug. Around line 196 of the extension, find these two lines:

! 1 word for static bitmap pointer + 8 word v2v header + 1 word per 16 entries in the bitmap nbmp = DT_Alloc((1+VTOVS_HDR_WORDS)*WORDSIZE + (n+15)/16);

And change the second line to read as follows:

	nbmp = DT_Alloc((1 + VTOVS_HDR_WORDS + ((n+15)/16)) * WORDSIZE);

If this works for you then I’ll release an update.

Thanks to everyone for the responses.

@VictorGijsbers

Thank you for your suggestion. Perhaps I’m in an unusual situation because my ISP eliminated native access to usenet earlier this year, which leaves me with no quick means to participate in such. I did take a quick look at the Google Groups FAQ, and given your suggestion I’ll certainly continue to do some more reading about it (my initial reaction to what I was reading in the FAQ was that using it would be like posting a big bullseye for spammers on my back, but perhaps that’s not at all correct).

Heading a bit off topic, I can of course read newsgroups however through web-based means (including through Google Groups) and I wanted to take this opportunity to say thank you as I noticed you reposted another somewhat obscure topic I had here last week to the r-a-if; it was very generous of you to take time to do that, and I’m sincerely grateful for the help (that issue in the other thread was very puzzling to me, and although I wish Inform had the extra functionality I was looking for at least now I know I’m not actually doing anything too implausible even though it’s not permitted by the program). I can definitely use all the assistance I can get, and I am very appreciative of the genuine spirit of support and helpfulness I’ve experienced from members of the IF community like yourself and others.

In the meantime, I’d also like to say thank you to the administrators and staff of the Intfiction.org forum for providing this easy-to-use and accessible alternative forum for those like myself seeking help with IF questions.

@Jesse McGrew

Thank you very much–I think that fixes everything.

I made the change you posted in the Dynamic Objects extension, saved it, and tried the “tissue-test” scenario shown above. Everything worked perfectly (no “Programming error” message and no crashing), so I tried out the revised extension with my main project as well. I currently have only two instances of dynamic object creation in that code, but they are completely unrelated apart from utilizing the dynamic object creation process (one mentioned above where the game needs to create some liquids on the fly, the other involving removing ammunition from the ammunition magazines of some weapons I designed); however I’m fairly sure the larger code also contains at least one usage of every other type of I7 relation under the sun as well (with the possible exception of things relating to each other in groups, although I certainly have people relating to each other in groups included). In any case it seemed like something that would be a fairly definitive test. Both actions worked smoothly with no hint of error or crashing, and therefore I feel pretty confident in saying the fix you posted here definitely solves the problem.

Thanks for the fix, the quick response, and in general for the Dynamic Objects extension as the extension is definitely something I’ll be using frequently to solve what would otherwise be some fairly intractable problems in my coding of a rather complex world-model.