Is this memory allocation issue

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

Yesterday I've spent more than two hours trying to figure out why a piece of code will compile with no errors but not run at all.

I was playing with a SD card sector reader / writer code and it happened I wanted to make a 512 elements array with some data in order to check when reading the SD card. For this I've wrote inside main:


int array1[520]
int k

for (k=0;k<512; k++) {

array1[k] = k; // see text below
array1[512-k]=k;

}

This compiled OK, however the execution stops completely at the beginning of the for loop. If I commented out the line see text below above, the execution was normal.

If I defined int array1[520] out of the main (global) the program would not run at all.Or make weird things as looping the code between the beginning of the main up to this point. Like this point was a GOTO main() again.

After more than an hour of changing names even the MCU ( ATMega168). I decided to decrease the size of the array to 20 and then everything worked OK.

So, it happens to be that there was another 520 elements array declared in the code, so ( apparently) the atmega168 memory was two small to hold both arrays.

What I do not understand is why the compiler or the linker did not notice this problem and produces and hex file which will not work.

I have no clue on how the compiler deals with the FLASH, EEPROM and RAM . I think that the variables reserve RAM only ?

I believe that the solution here should be to use PROGMEM to store the array. But in this case, the values can not be changed at run time right?

Anyway, i would like to see what people with much more knowledge than me can comment on this . Anyway, please remember this post when you are having code doing unexplainable things!!

Jose

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
So, it happens to be that there was another 520 elements array declared in the code, so ( apparently) the atmega168 memory was two small to hold both arrays.
It is even too small to hold one of these arrays.
"int array1[520]" occupies 1040 bytes of RAM, but you have only 1024.
You should be more careful with your data types. I would bet you need only single bytes in the array, not ints.

unsigned char array1[520];
or
uint8_t array1[520];

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Single bytes won't be able to hold values > 255, and he is storing 0-512...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
array1[512-k]=k; 

With the loop that you have, this will index outside of the array (when k = 0 you will be indexing element 512, which does not exist).

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:

array1[512-k]=k; 

With the loop that you have, this will index outside of the array (when k = 0 you will be indexing element 512, which does not exist).

Why shouldn't it exist?
(Apart from the fact that the memory is not big enough)

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

n1ist wrote:
Single bytes won't be able to hold values > 255, and he is storing 0-512...
Yes, but the loop looks like some kind of test. I doubt that he need more than single bytes in the final use of this array, because he wants to store data for/from a SD-card in it.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:
Koshchi wrote:

array1[512-k]=k; 

With the loop that you have, this will index outside of the array (when k = 0 you will be indexing element 512, which does not exist).

Why shouldn't it exist?
(Apart from the fact that the memory is not big enough)

Because in C indices start at zero, so the last element is 511, not 512.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

except the array was declared with a length of 520 ;)

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jayjay1974 wrote:
Because in C indices start at zero, so the last element is 511, not 512.
No, the last element is 519.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys,

Thanks a lot for the answers, to clarify there is a typo, the loop runs to 256 not 512 , so there is not such overlap. The main problem is as stated by the first reply, that I am overflowing the RAM of the mega168.

But my concern is why the compiler do not even warns about this. I know that the programmer must be disciplined enough to have all the variables under control which is fairly easy in an small program , but when you may find yourself in a big program, you may get in this situation it will compile OK and the program will behave completely unexplainable. I've learnt my lesson and just sharing with you not to waste time and check this whenever a program is not doing what it is supposed to do. Thanks ,

Jose

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the compiler will warn you... you must have missed it, or otherwise suppressed the warning somehow.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

it will compile OK and the program will behave completely unexplainable

This is also kind of the reason that lint / splint / etc. exist.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jofre wrote:
But my concern is why the compiler do not even warns about this [memory overflow].

I made a quick and dirty test, allocating much more local and global variables than a 'M8 has - and, lo and behold, no warning from compiler nor linker.

Now the reasons: global variables sounds to be easy and the linker may catch that, but that would annoy folks who actually DO have more SRAM (external) than it's onchip. A mechanism would need to be invented to allow for manual setting of SOME limit (and that then should include manual stack and heap watermarks settings, too).

Local variables are even harder, as they are allocated on stack.

JW