-1

I define a static global array of struct which has some elements defined as pointers. This array will be filled and managed by a static library I use in the project. I find that the array is correctly filled by the library. After a couple of seconds, some values in this array is overwritten somewhere else. After debugging, I found that the Stack Pointer (SP) points to the same memory location where some members of the array are saved and therefore will overwrite the value when pushing to the stack when for example a function is called and its local values are saved in the stack.

My question is: what can cause the stack pointer to point to a memory location that is occupied by another variable? How can I debug this problem further?

I know that my question is general but unfortunately I can't provide a minimal code that reproduces the problem as it is a big project and I don't know exactly which part of the code can cause such a problem.

Salahuddin
  • 1,617
  • 3
  • 23
  • 37
  • 1
    You seem to allocate the memory pointed to on the stack... For example, a local variable. – the busybee Jun 09 '22 at 14:35
  • @the busybee. Thanks for the quick answer. That is true. This is the problem. I define an array as a local variable (on the stack). Assign its address to an element of the global array. This is why the content of the buffer will be overwritten later. – Salahuddin Jun 09 '22 at 14:41
  • Don't know if I should delete the question or keep it? – Salahuddin Jun 09 '22 at 14:42
  • Do you think that others with the same error will look for it **and** find it? If yes, keep it. – the busybee Jun 09 '22 at 14:47

2 Answers2

1

This is almost always caused by stack overflow and by a bad RAM memory layout causing the stack to overflow into the .data segment. Also obviously avoid bad practices such as intentional/accidental use of recursion.

Troubleshooting:

  • Soon as the SP is initialized by the CRT/start-up code, then have your debugger fill the whole stack area with some known magic number like 0xAA.
  • Set a write breakpoint at the very bottom of the stack (at the first 0xAA, assuming down-counting stack).
  • If you just halt the program at a random place, you'll be able to see how many of the 0xAA your program has munched up. If all of them are gone, your stack is toast.
  • If you reach the write breakpoint at the bottom of the stack, you'll be able to tell which code was responsible for the most recent write.
  • A modern MCU and a half-decent debugger with trace may reveal more detailed info if you view the backtrace.

Other less likely but also possible causes:

  • Array out-of-bounds or pointer corruption bugs overwriting things like return addresses on the stack or writing at random locations.
  • "Runaway code" caused by something like the above, the program counter executing at arbitrary memory locations.
  • Beginner mistakes such as returning pointers to local variables from a function or otherwise using pointers to local data which has gone out of scope.
  • Messing up manual push/pops or function calling convention in inline assembly.
Lundin
  • 195,001
  • 40
  • 254
  • 396
-1

This answer is for the beginners or others who may face the same problem to clarify the problem and to explain how did I figured it out.

A stack is a section in the memory where local variables are stored. Local variables are the non-static variables defined inside a function. Another usage of the stack is to store the address of the latest executed command before jumping to another function or interrupt service routine (ISR) so that CPU knows from where should it continue when it finishes executing the ISR or the other function. When a local variable is defined, its value is saved in the stack. As soon as the function finishes executing, this local variable doesn't exist anymore and its address in the stack is free to be used.

The problem as @the_busybee pointed out was because of defining a local array and assigning its address (which is in the stack) to a globally defined pointer. Then the global pointer itself is saved in .bss memory section while the address it is pointing at is in the stack.

Now how did I figured out

  • After posting the question I was trying to edit it to make it more clear. This helps you clarifying your thoughts (like the rubber duck debugging method. Many times I found the answer to the question just by trying to formulate it in a clear way.
  • Then I was thinking that why does the stack pointer point to the address of a globally defined variable.
  • To make sure that this assumption is correct I checked the address where the global variable is defined. It was 0x20003F4. Then I checked the address saved in the globally defined pointer. It was 0x20006FD0.
  • I thought then, what if this pointed-at address is a part of the stack area? I checked the .map file and found that .stack starts at address 0x20006c00 and has the size of 0x400. This means that 0x20006FD0 is indeed part of the stack.
  • Then I remembered that I defined the array pointed at by the global pointer locally in a function.
  • At this point I saw the comment of the_busybee and cancelled editing the question and start writing this answer :)

I hope this answer helps

Salahuddin
  • 1,617
  • 3
  • 23
  • 37
  • So basically just the embedded version of [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Lundin Jun 10 '22 at 11:41