Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

About Stack-Heap Collision...

Rocco Sirnah
Registered User
Join date: 13 Jul 2008
Posts: 13
12-28-2008 09:22
I made a game like Zyngo.
I wrote about 1000 lines of code.
It works great but often I have Stack-Heap Collision error.
I tried to check free memory and, wow, I have only 700 bytes free...
Strange... from 64k. I remember the old Comodore64, I made very huge programs with it.

In my Mono script I used several lists and I used llListRandomize. Maybe that the problem?
I have just one big list with 90 strings. Any String is the key of the image of a number (from 1 to 90).

How I can solve this problem?
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
12-28-2008 10:04
When you assign a list it makes a copy of the whole list. Each UUID takes up 36 characters because SL tracks UUIDs as strings instead of the 128 bit numbers they represent. In Mono that's 72 bytes because Mono uses Unicode strings. There is also additional overhead for the string structures and the heap tracking each chunk of memory allocated for each string. If you make a list of numbers from 1..90, and randomize that, and use it as an index into the main list, you'll be throwing around lists that have 4 bytes per element instead of 70+ bytes per element... a substantial memory savings.
_____________________
Argent Stonecutter - http://globalcausalityviolation.blogspot.com/

"And now I'm going to show you something really cool."

Skyhook Station - http://xrl.us/skyhook23
Coonspiracy Store - http://xrl.us/coonstore
Rocco Sirnah
Registered User
Join date: 13 Jul 2008
Posts: 13
I made that...
12-28-2008 10:56
I made that. I randomize an integer list and I use it as an index to access to 90 key's list.
I created the list in this way:

Numbers=["String1","string2","string3"];
Numbers+=["string4","string5","string6"];
.
.
.
.
.
Numbers+=["string88","string89","string90"];

Is that right?
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
12-28-2008 11:11
I recommend initializing the list at the global level with:

numbers = [
"string1","string2","string3",
"string4","string5","string6",
...
];


If that's too big, split the list into (at most) two or 3 parts and reassemble it in default's state_entry. Making it out of lots of small lists is the worst way to do it.
_____________________
Argent Stonecutter - http://globalcausalityviolation.blogspot.com/

"And now I'm going to show you something really cool."

Skyhook Station - http://xrl.us/skyhook23
Coonspiracy Store - http://xrl.us/coonstore
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
12-28-2008 11:16
First, make sure you really are compiling in Mono -- if you compile from your inventory, it's not mono any more.

Second, review your data structure usage to see if it could be more optimal.

Third, make sure you're using functions for repeated code segments. In Mono, the compiled code takes quite a bit of your 64K of memory.

Last, if you're still out of memory, you'll have to break up your script into multiple scripts. For example, one script can act as a data store to which you send LMs and expect responses with the requested data. Note that this usually complicates the code considerably, though sometimes it can work the other way.
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
12-28-2008 11:22
From: Argent Stonecutter
I recommend initializing the list at the global level with:

numbers = [
"string1","string2","string3",
"string4","string5","string6",
...
];


If that's too big, split the list into (at most) two or 3 parts and reassemble it in default's state_entry. Making it out of lots of small lists is the worst way to do it.


Hmm. Actually I would recommend doing it the way he had it (using '+='). If you have a bunch of global variables with small lists and you assemble them into a larger list, you'd want to be careful to unassign each of the smaller lists after adding them on, or you'd be taking up at least twice as much memory as you needed. A useful way to initialize variables that need more than the usual static values is to follow the pattern:

CODE

// Global variables
integer i1;
integer i2;
string s1;
list l1;

integer initialized = FALSE;
init()
{
if (initialized)
{
return;
}
initialized = TRUE;

i1 = ...;
i2 = ...;
s1 = ...;
l1 = ...;
}

default
{
state_entry()
{
init();

// The rest of your code
}
}


That should be a good way to stack together the large list you need if it has more than 72 elements.
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
12-28-2008 11:25
If you build it out of little lists in the code, the lists still exist and can't be "unassigned". Also, whether you initialize global variables or not the compiler generates the same code to initialize them, including allocating space on the heap for an empty initial value. That is, the generated code, either in CIL (Mono) or LSL2 is identical for:

integer i = 0;

And:

integer i;

Regardless, though, the main point is that you want to build it out of the largest chunks you can.
_____________________
Argent Stonecutter - http://globalcausalityviolation.blogspot.com/

"And now I'm going to show you something really cool."

Skyhook Station - http://xrl.us/skyhook23
Coonspiracy Store - http://xrl.us/coonstore
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-28-2008 15:54
does this still work for conserving memory in mono.

blah = llListRandomize( (blah=[]) + blah, 1 );

have to admit I haven't tested it with all that new space available, but it was the method that worked in LSO to prevent doubling (never can thank strife enough for that method/snippet)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
12-28-2008 16:19
From: Void Singer
does this still work for conserving memory in mono.

blah = llListRandomize( (blah=[]) + blah, 1 );

have to admit I haven't tested it with all that new space available, but it was the method that worked in LSO to prevent doubling (never can thank strife enough for that method/snippet)

It doesn't make any difference with MONO.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Rocco Sirnah
Registered User
Join date: 13 Jul 2008
Posts: 13
Thank you...
12-29-2008 01:34
Putting my static data in two list (one global and one local) and merging them, I solved problem...

Now I have:

list Lista;

Init()
{
Lista=["60 ROWS"];
list Lista2=["30 ROWS"];

Lista=Lista+Lista2;
Lista2=[];
}

Now I haven't error messages...
Very Keynes
LSL is a Virus
Join date: 6 May 2006
Posts: 484
12-29-2008 04:57
Rather Try:

list Lista;

Init()
{
Lista = ["60 ROWS"]
Lista += ["30 ROWS"];
}

or even:

list Lista;

Init()
{
Lista=["90 ROWS"];
}
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-29-2008 08:11
From: Jesse Barnett
It doesn't make any difference with MONO.

that's a shame...
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
12-29-2008 10:20
From: Void Singer
that's a shame...

I THINK it doesn't make any difference because the memory accounting bug that it got around isn't present anymore. NOT a shame. ;)
Escort DeFarge
Together
Join date: 18 Nov 2004
Posts: 681
12-29-2008 12:14
From: Lear Cale
First, make sure you really are compiling in Mono -- if you compile from your inventory, it's not mono any more.

...yep, that's bit of a pain sometimes... I feel a Jira feature request coming on...
_____________________
http://slurl.com/secondlife/Together
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-29-2008 13:31
From: Hewee Zetkin
I THINK it doesn't make any difference because the memory accounting bug that it got around isn't present anymore. NOT a shame. ;)

I wasn't aware it was so much of a bug, more a side-effect. granted some of those functions should never have taken up double variable memory to begin with (randomize is a good example). I say shame because some obviously still do, although with the new limits on memory imposed by mono, it doesn't crop up as often. (not many people code things that would use all of the space in mono especially after getting used to the old limits)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
12-29-2008 14:11
From: Void Singer
that's a shame...


Quite the opposite! It's fantastic that the silly trick isn't necessary.

In other words, Mono is way better because it doesn't waste the space for that case.

Thanks to Strife for finding the optimization, but thanks even more to Mono for making it unnecessary.
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
12-29-2008 14:15
From: Hewee Zetkin
I THINK it doesn't make any difference because the memory accounting bug that it got around isn't present anymore. NOT a shame. ;)


My understanding is that it wasn't an accounting bug, but rather, memory fragmentation due to making an unnecessary copy (due to call-by-value semantics, even for "lvalues" -- that is, things to be stored to rather than to be used). Strife's optimization worked by assigning the empty list to this "copy" before passing it.
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
12-29-2008 14:22
I'm pretty sure the best solution is this:

CODE

list ListA = [ ... 90 rows ... ];


That's if the script never modifies the list and so it doesn't need to be reinitialized.

If you use this:
CODE

list ListData = [ ... 90 rows ... ];

list ListA;

init() {
ListA = ListData;
}

then you have two copies of the list, taking twice as much space. This is true even if it's initialization of a local variable, as in the OP's post above.
Rocco Sirnah
Registered User
Join date: 13 Jul 2008
Posts: 13
Problem totally solved!
12-29-2008 23:38
Every script in my linked objects can use 64K of memory. So, I moved my big list inside an other linked object, called slave (!). When Main script has to know something, it calls Slave with llMessageLinked. Slave takes data from big list and replies to Main...
Now Slave has 47K free and Main 14K free...

Now it's all OK!

Thank you to everybody...
Escort DeFarge
Together
Join date: 18 Nov 2004
Posts: 681
12-29-2008 23:53
If every number doesn't *have* to be a texture -- why not simplify the whole thing and use indexing into one large texture a la xytext? The texture would stay loaded and so display changes would be faster too.

/esc
_____________________
http://slurl.com/secondlife/Together
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
12-30-2008 02:38
From: Lear Cale
I'm pretty sure the best solution is this:

CODE

list ListA = [ ... 90 rows ... ];



Aren't literal lists still constrained to a maximum of 72 (or was it 70?) elements?
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
12-30-2008 15:49
From: Hewee Zetkin
Aren't literal lists still constrained to a maximum of 72 (or was it 70?) elements?

Ah! Thanks for the tidbit I was unaware of.

Personally, I'd put the data in a notecard and read it in, but then, I do notecards daily. I'm adding another one to MLPV2 as we speak, for configuring SWAP ... we'll see if that pans out. :)

In any case, the OP has a good solution here, applicable to a number of problems, and worth knowing how to employ in the future.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-30-2008 19:43
it's 72 at compile time for predefined lists, memory limit once it's running
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Kain Cleaver
Registered User
Join date: 24 Jan 2006
Posts: 178
12-31-2008 20:29
its probably rare that you see a major game creator help someone here like this but let me give you a hint..

when it comes to shuffling your board and laying the textures out .. have a seperate script do that work.. and then message the outcome to the main script.

so say you have 25 numbers .. have a shuffle script do the list randomizer, the texturing of the boxes, then.. have it send a link message using LINK_THIS .. in the string field have the 25 numbers seperated by ; (ex : 1;2;3;4;5;6;7)

on your main script after the player pays.. have the main script go into a waiting state. where it waits for the message with a special number to know its the right message.. something like if (num = 123321)

then have the main script make it into a list.. and break the list into individual integers.

this method will save alot of script memory because the randomization and the texturizing of the individual squares do take up alot.

i dont know if your doing multi sided prim.. or if your doing an individual prim per button thing. but a big help is to have the buttons message a number to the main script as well.

say you have a grid of 25.. each button labled 1 - 25.. this way you can do a simple list of something like

if (str == "press";)
{
if (num == 1){if (a1 == spinner1){ do stuff}}
if (num == 2){if (a2 == spinner1){do stuff}}
ect}

youd only need 25 out comes of the number.. and compare it to one of the 5 spinners.
so spinner 1 would have to match up with a1 - a5 spinner2 would be a6 - a10

its not hard to do.. you just have to find a way of having other scripts do alot of your dirty work..

same goes with general payout and score detection..

have the main script send the final score to another prim and let that prim detect if it broke the instant win score and let it pay out insted of your main script

same goes with your settings notecard.. have one script decypher it.. and use your description field as a data holder for your main script to read and determine.
Kain Cleaver
Registered User
Join date: 24 Jan 2006
Posts: 178
12-31-2008 20:34
dont get me wrong btw.. im all for new game creators coming out to supply SL with new games.. dont do a direct zyngo clone... the market is saturated with them. if your going to do something like it.. make sure you introduce new gameplay. do something different and exciting... dont try and copy the success of others.. make your own!

trust me on this one! there is plenty of opportunity in SL for game creators. and if your idea is new and unique and fun people WILL buy it.
1 2