#161588 - DiscoStew - Wed Aug 06, 2008 9:34 pm
Ok, I've found some really odd behavior when working on my DS projects. The location of variables in memory are shifting. The data in them remain intact, but anything to do with addresses are shifting.
I noticed this odd behavior when I was fixing a few bugs in my program that dealt with shortcut pointers directed to data in memory that was loaded from a file. At the beginning of a function, the variable was in an area of memory, but when I checked that variable's address at the end of the function, it had shifted a couple dozen bytes. I checked other variables and structures, and the same thing was happening to them too, shifting the same number of bytes. However, it seems that it's only happening in one of my functions that gets called only once for the moment. Like I said before, all the data remains intact, so even with these shifting addresses, the data is shifting with them, staying in harmony.
Although it is hardly affecting my DS programming, it was just something odd that I stumbled across.
_________________
DS - It's all about DiscoStew
#161589 - Dwedit - Wed Aug 06, 2008 9:37 pm
I think you may have a memory leak.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#161590 - DiscoStew - Wed Aug 06, 2008 9:39 pm
I don't think it's a memory leak, because it's even affecting variables that are declared at the start of the program, even before any memory allocation via malloc and such.
_________________
DS - It's all about DiscoStew
#161594 - silent_code - Wed Aug 06, 2008 10:13 pm
I got helped by posting some sources yesterday (also very odd behaviour - it turned out to be a silly little mistake) and I believe you could be helped when posting something, too. :^)
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.
#161598 - DiscoStew - Wed Aug 06, 2008 11:19 pm
When I get home today, I'll put something together.
_________________
DS - It's all about DiscoStew
#161606 - DiscoStew - Thu Aug 07, 2008 4:29 am
Ok, I think I have something small enough that can show it.
Code: |
unsigned int fsInfo;
unsigned int fsSize = 0;
if(!fatInitDefault())
{ iprintf("\x1b[9;0HFile System initialization failed."); while(1); }
//1st two-liner
iprintf("\x1b[9;0HTest -> %04X", &fsSize);
while(1);
FILE *levels = fopen("/data/level001.dat", "rb");
if(levels == NULL)
{ iprintf("\x1b[9;0HCould not open the Level files."); while(1); }
fread((void*)&fsInfo, 4, 1, levels);
if((fsInfo != 0x00000000) )
{ iprintf("\x1b[9;0HFound incompatible Level file."); }
fclose(levels);
//2nd two-liner
iprintf("\x1b[9;0HTest -> %04X", &fsSize);
while(1);
|
It's messy, I know, but when I run this as is, the first "iprint" that uses '&fsSize' gives the address in one area of memory (and of course, because of that while loop, nothing else happens. But, should that two-liner be commented out, when the code get to the 2nd two-liner with 'iprint' and the while statement, the address of fsSize shifts a couple of words over.
My usual code isn't like this, but the shift in addresses is even larger over smaller sections of code. When I first encountered this odd behavior, it was with moving only a single 'two-liner' from one place in code to another a few lines down, and a greater shift in addresses were showing. Even addresses of addresses were shifting when nothing was being done with them after being set once and left alone.
The only thing I can see that could be showing this distortion is something with 'iprintf', and dealing with addresses. If that is the case, then I need a better method for examining them.
_________________
DS - It's all about DiscoStew
#161644 - M3d10n - Fri Aug 08, 2008 10:42 pm
Code: |
iprintf("\x1b[9;0HTest -> %04X", &fsSize); |
The printed values will change everytime because you're printing the location of &fsSize, which is a pointer to fsSize that's being created temporarily on each iprintf call and most likely resides on a register.
It's more or less like you're doing this:
Code: |
int foobar = 100;
int *foo = &foobar;
int *bar = &foobar;
|
The variables "foo" and "bar" are pointers pointing to the same location in memory (foobar), but each one resides on a different area of memory. That's what you're seeing in your iprintf() calls.
Summing up: don't add "&" to your iprintf() parameters, all you're gonna see is the address of some register.
#161646 - josath - Sat Aug 09, 2008 2:11 am
I think M3d10n is wrong. &foobar should always give you the address of foobar. If you did: Code: |
int *foo = &foobar;
int *bar = &foobar;
iprintf("%08X %08X\n", foo, bar); |
You should get the same exact address printed twice
Now here's where I'm confused. Are you actually printing out the address of a particular variable in two different places in your code and getting different addresses, in the same compiled program? Because you said Quote: |
But, should that two-liner be commented out |
and that makes me think you are commenting out the first iprintf statement. If you change code around, then of course the compiler might decide to put things in memory differently, due to whatever it thinks is most optimal. It may be that simply moving an iprintf statement around makes the compiler decide to place a variable one place or another. But the key thing is that the address should not change within a single program.
#161648 - DiscoStew - Sat Aug 09, 2008 3:55 am
The variable I am getting the address of is not changing places in the program. The one I'm specifically checking is the very first in the function. My major test of it was having 6 iprintf statements throughout the function, each accessing the address of the first variable, with the last statement with the while loop. In that, all the iprintf statements show the same address, but as I start commenting out the iprintf from the bottom up (and moving the while loop to the previous statement) from 6 iprintfs to 1 iprintf, they all show the same address, but that particular address is not the same as it was before with a different number of iprintf statements. And with that, the shift in the address has been from 4 bytes to even a 100 byte difference.
You think it might just be how the compiler deals with iprintf? Considering the nature of the iprintf function vs others, it isn't quite limited to how many values you can put into it, only that you have as many in the string to place each into.
_________________
DS - It's all about DiscoStew
#161649 - josath - Sat Aug 09, 2008 4:46 am
I don't think it's iprintf in particular causing the problem, it's just that the compiler randomly places variables in memory, and changing code that references that variable in any way can change the place it decides to put it in memory.
#161650 - sgeos - Sat Aug 09, 2008 6:27 am
josath wrote: |
it's just that the compiler randomly places variables in memory, |
The compiler systematically places variables in memory, and to the best of my knowledge compilers have almost complete freedom when it comes to where and how they place things. What can and can not be done is in the C standard, if you care to read it.
josath wrote: |
and changing code that references that variable in any way can change the place it decides to put it in memory. |
Adding and deleting lines, reordering lines, etc, can and probably will change where the compiler decides to put things, depending on what you are doing. Commenting out a line is the same as deleting it as far as the compiler is concerned. Comments become whitespace. Whitespace should have no effect on the resulting output.
Because small changes can completely change where variable are located, things like gameshark codes don't work with different language versions of the same game, even if 99% of source code and data is exactly the same. Recompiling with changes changes things. =)
FWIW, anything that lives on the stack will probably change locations during the life of a single program execution.
-Brendan
#161651 - zeruda - Sat Aug 09, 2008 7:21 am
M3d10n wrote: |
Code: |
int foobar = 100;
int *foo = &foobar;
int *bar = &foobar;
|
The variables "foo" and "bar" are pointers pointing to the same location in memory (foobar), but each one resides on a different area of memory. That's what you're seeing in your iprintf() calls. |
foo and bar in this case both point to the address of foobar. If you print foo and bar you will get the same value, &foobar. If you printed &foo and &bar then you would get two seperate addresses of foo and bar.
I'd suggest try the tests by setting a pointer to fsSize and do your print tests with that.
Code: |
unsigned int fsSize = 0;
unsigned int *PointertofsSize = &fsSize;
iprintf("\x1b[9;0HTest -> %04X", PointertofsSize);
|
Seems the most likely culprit is the iprintf statement although it could be the fread. It could be the memory management but when you do unsigned int fsSize = 0; that should create the variable in memory and assign 0 to it there and then, so I don't really see why changes later in the function would be the cause. Oh, and when unexpected behaviour occurs a make clean, make can sometimes fix it, just in case you ain't tried that.
#161653 - silent_code - Sat Aug 09, 2008 9:38 am
I don't know if somebody had pointed this out already, but there's %p for printing pointers.
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.
#161655 - Cearn - Sat Aug 09, 2008 11:17 am
zeruda wrote: |
Code: | unsigned int fsSize = 0;
unsigned int *PointertofsSize = &fsSize;
iprintf("\x1b[9;0HTest -> %04X", PointertofsSize);
|
Seems the most likely culprit is the iprintf statement although it could be the fread. It could be the memory management ... but when you do unsigned int fsSize = 0; that should create the variable in memory and assign 0 to it there ... |
This isn't quite true. In general, local variables don't go in memory at all but in registers. There are some exceptions to this, one of them being when you take the address of it (like in the second line). In that case, like M3d10n said, a temp variable is allocated on the stack and referenced via an offset from the stack pointer (SP+x).
The address on the stack pointer depends on a number of things, mainly the level of function calls. Inside a function, GCC tends to assign the local stack at the top of a function so that SP won't change in its scope. However, the amount of local stack space and how it is used can change when the function is altered. For example, this is what I get when I compile DiscoStew's code with and without the first two-liner:
Code: |
@ With 1st two-liner
push {lr} @ - decrease SP by 16
sub sp, sp, #12 @ /
mov r3, #0
str r3, [sp, #4] @ Put fsSize on stack. &fsSize= SP+4
bl fatInitDefault
cmp r0, #0
bne .L48
ldr r0, .L52
bl iprintf
... more
|
and
Code: |
@ Without 1st two-liner
push {r4, lr} @ - decrease SP by 16
sub sp, sp, #8 @ /
mov r3, #0
str r3, [sp] @ Put fsSize on stack. &fsSize= SP
bl fatInitDefault
cmp r0, #0
bne .L48
ldr r0, .L57
bl iprintf
... more
|
In both cases, SP decreases by 16, but in the former the zero is placed at SP+4, where as it goes in SP+0 in the latter: a difference of 4 bytes. If you allocate local arrays, the difference will be even larger.
@ DiscoStew:
What are the addresses of your shifting variables? Are they in main RAM or on the stack? Are they global or local?
#161659 - M3d10n - Sat Aug 09, 2008 2:08 pm
Indeed, most likely your local variable is on a register and printing a pointer to it won't return the same result everytime. Getting a pointer to it in another variable might force the compiler to lock it down on the stack or something.
#161672 - Sunray - Sat Aug 09, 2008 10:16 pm
Try making it volatile.