EmbDev.net

Forum: ARM programming with GCC/GNU tools C++ STL and STM32


von Thomas H. (Guest)


Rate this post
useful
not useful
Hi,

I have a problem with the C++ STL on the STM32. The following code works 
as expected on my hardware (chinese board with STM32F103..)
1
int main(void)
2
{
3
  char Line[512];
4
  std::list<std::string> *pHistory;
5
  pHistory = new std::list<std::string>;
6
7
[ ... all the necessary initialisation ...]
8
9
10
  while (1)
11
  {
12
    printf("Please enter a line.\n");
13
    fgets(Line,512,stdin);
14
    std::string CurrentLine(Line);
15
    if (CurrentLine.find('-') == 0){
16
        pHistory->sort();
17
        for(std::list<std::string>::iterator p=pHistory->begin();p!=pHistory->end();++p) {
18
           printf("%s",p->c_str());
19
        }
20
    }  else {
21
        pHistory->push_back(CurrentLine);
22
        printf("%s",CurrentLine.c_str());
23
    }
24
25
  }
26
}

When I put the list on the stack instead of the heap, i.e. change the 
declaration of history to
1
  std::list<std::string> History;
(and change the rest accordingly), the code crashes before printing the 
first line. It also happens, when I declare history outside of the 
function.

Development environment is CodeSourcery on Linux, if necessary I can 
post the whole Eclipse project.

Thanks for thinking!

T

von HaseHase (Guest)


Rate this post
useful
not useful
Hello,

there is to low stack memory for the list "History". At program 
execution you get a stack overflow error. But you can not see it.

You should place lists always at the heap.

CU,
Hase

von Simon (Guest)


Rate this post
useful
not useful
Why is that? std::list is just a doubly linked list, so the object 
itself should only contain two pointers (to the first and last element), 
am maybe some size info.

If put on stack, the elements themselves are put on heap, too, or am I 
wrong?

I don't quite see the reason for the crash...

von HaseHase (Guest)


Rate this post
useful
not useful
Hello Simon,

you declare

std::list<std::string> History; // List of strings. Not a list of 
pointers to strings. Maybe i am wrong?
...
 std::string CurrentLine(Line); // local string at the stack; not a the 
stack
...
 History.push_back(CurrentLine); // Put the string to the list
                                 // My opion: the string is copied to 
the list

Posible solutions:
1. Make a list of strings
2. Declare the string (buffer) at the heap.

char *pCurrentLine = new char[255];

cu

von Thomas H. (Guest)


Rate this post
useful
not useful
Hello Hase,

I agree that I strain the stack a bit, but out of the 64k RAM in the 
STM32, I have less than 8k for .data and .bss sections. The remaining 
56k are used for heap and stack. The initial stack pointer is set to the 
end of RAM and the heap grows upwards from the end of the .bss section 
(by means of the library function _sbrk).

So the RAM should be available to either stack or heap.

But I got some points for research from your second post, so I will do 
some experiments with stack vs. heap variables and keep you updated.

Bye,

Thomas

von Simon (Guest)


Rate this post
useful
not useful
Hello Hase,

I'm still not really sure about it. Yes, of course it's a list of 
strings, and not a list of pointers to strings. But let's have a look at 
what a list does: At the beginning, it's empty. So what is put on the 
stack? I think, really just a small structure containing two pointers, 
both pointing to NULL (or something like that).

Now, push_back() adds an element, a.e. a string to it. So, what happens? 
I'm quite sure, a structure containing a string and a "next" pointer is 
created on the heap. No matter if the list itself is put on the stack or 
on the heap.

What you put on the stack or on the heap is just the "initial structure" 
containing the "entry points", a.e. the pointers to the first and the 
last element in the list.


Am I wrong?

von Simon (Guest)


Rate this post
useful
not useful
I forgot:

You wrote:

> std::string CurrentLine(Line); // local string at the stack; not a the
>stack
>...
> History.push_back(CurrentLine); // Put the string to the list
                                 // My opion: the string is copied to


Yes, that's what happens, I think. The string is put on the stack first, 
than, by push_back, a new element is created on the heap, including a 
string object, which is crated using a copy constructor taking 
CurrentLine as the argument.

So, I don't much stack usage here.

von Simon (Guest)


Rate this post
useful
not useful
I don't SEE much stack usage here, I meant... sorry, it's late... :-)

von HaseHase (Guest)


Rate this post
useful
not useful
Hello,

why do you think that the string is allocated at the heap?
The string is allocated  at the local stack and the list is allocated at 
the local stack.
Please use a complier at a pc and check it.

CU

von Simon H. (simi)


Rate this post
useful
not useful
Still me, but now logged in:

The list is allocated on the stack, as you say. But what exactly IS a 
"list object", when it's allocated? It's an object containing only a 
"first" and a "last" pointer. Do you agree?

Then, here:
std::string CurrentLine(Line);

a string object is allocated at the stack, as you say. (btw: Depending 
on the implementation, this means, that on the stack, there is more or 
less only a pointer, and on the heap(!!), the real data is allocated. 
But as I said, this depends on the implementation of std::string. Some 
implementations I've seen, put small strings completely on the stack, 
and larger ones on the heap. But let us assume now, that the string is 
allocated entierly on the stack.)

Now let's look at this line:
pHistory->push_back(CurrentLine);

You think, that the object CurrentLine is appended to the list, but 
that's not true. What really happens, is as follows:

The list object (which, as you say, is located on the stack) allocates a 
"list item" on the heap. This list item has room for:
-a "next" pointer
-a "previous" pointer
-a string object

Then, CurrentLine is copied into this "list item" using a copy 
constructor.

Have a look at this:
http://www.cplusplus.com/reference/stl/list/push_back/

Could you explain, how a list object could ever push_back() items on the 
stack? That's impossible! push_back has its own stack frame, which is 
"cleaned up" (by setting the SP) just after exiting. So, the item would 
be "deleted" (a.e is not accessible any more) as well, as soon as 
push_back() ends.

Greets
Simon

von Thomas H. (Guest)


Rate this post
useful
not useful
Hey guys,

interesting discussion.

I tend to agree to Simon, mainly because I cant imagine a way to 
'allocate' something on the stack while a function runs. Maybe its 
different with arm architecture, but with traditional (x86) 
architectures, the stack layout (aka stack frame) is fixed at function 
entry. So the only place to allocate something dynamically is the heap.

Which brings me back to my original question. I have some 56k from the 
end of the bss section to the end of the RAM, which are shared by the 
heap (growing upward) and the stack (growing downward). So how come, it 
is enough, when I explicitly allocate on the heap, and it fails, when I 
automatically allocate (parts of the objects) on the stack?

Greetings,

Tommi

von Simon H. (simi)


Rate this post
useful
not useful
Thomas H. wrote:
> Maybe its
> different with arm architecture,

no, this is a principle common to all architectures. So, the items are 
definitively allocated on the heap.

>Which brings me back to my original question.

I don't quite see where the problem could be. But have you tried 
stepping through the code to find out, what really makes the proc crash?

von Thomas H. (Guest)


Rate this post
useful
not useful
Simon wrote:

>But have you tried
>stepping through the code to find out, what really makes the proc crash?


I dont have a debugger for my hardware, so I can't do that.

I will work on my debug options, but for now one observation:

vector behaves the same as list, but deque works as expected.

Thank you for sharing your thoughts, I will go on to make more hardware 
peripherals (e.g. the debug port) available on my 'bare metal' system.

Tommi

von asda (Guest)


Attached files:

Rate this post
useful
not useful
asdasdasdasda

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.