push_back() causes program to stop before entering

2019-03-01 01:51发布

问题:

I'm developing in c++ for my STM32F3 Discovery board and using std::deque as queue. After trying to debug my code (directly on device with ST-link or in simulator), the code eventually stops at breakpoint before even entering my code in main(). However, SystemInit() configures board just fine..

I've traced this behavior down to using push_back() (and push_front) as commenting it out from code solves the issue. Through disassmebly I found that after using it, the execution stops at breakpoint instruction BKPT and won't move further after resuming execution. This instruction is part of _sysopen() call, with call path:

__main -> __scatterload -> __scatterload_null -> __rt_entry -> __rt_lib_init -> __rt_lib_init_atexit_1 -> _initio -> freopen -> _sysopen

What intrigues me is call to _initio, which is missing if push_back isn't used, because there is no __rt_lib_init_atexit_1. Introducing push_back also makes the code size go from 10 kB to 34 kB.

Might this be a result of some bad configuration or should I try another IDE? I'm out of ideas.

回答1:

I had the same problem. I learnt it has something to do with so called 'semihosting' and that I should build with my project file 'retarget.c' that contains definitions of the functions like '_sys_xxxx()' that are target specific driver level functions (many versions of 'retarget.c' are part of the Keil-MDK and also ca be found on web). So I did but then linker thrown errors similar to this:

Error: L6200E: Symbol _sys_open multiply defined (by arm_xxx_lib.o and retarget.o)
Error: L6200E: Symbol _sys_close multiply defined (by arm_xxx_lib.o and retarget.o)
...

I solved this by editing original 'retarget.c' so that functions defined in it will override the ones in Keil-MDK libraries. The new 'retarged.c' is here:

#include <stdio.h>
#include <rt_misc.h>

#pragma import(__use_no_semihosting_swi)

#include <rt_sys.h>

extern void $Super$$_sys_open(void);

FILEHANDLE $Sub$$_sys_open(const char *name, int openmode)
{
 return 1; /* everything goes to the same output */
}

extern void $Super$$_sys_close(void);
int $Sub$$_sys_close(FILEHANDLE fh)
{
 return 0;
}

extern void $Super$$_sys_write(void);
int $Sub$$_sys_write(FILEHANDLE fh, const unsigned char *buf,
              unsigned len, int mode)
{
 //your_device_write(buf, len);
 return 0;
}

extern void $Super$$_sys_read(void);
int $Sub$$_sys_read(FILEHANDLE fh, unsigned char *buf,
             unsigned len, int mode)
{
 return -1; /* not supported */
}

extern void $Super$$_ttywrch(void);
void $Sub$$_ttywrch(int ch)
{
 char c = ch;
 //your_device_write(&c, 1);
}

extern void $Super$$_sys_istty(void);
int $Sub$$_sys_istty(FILEHANDLE fh)
{
 return 0; /* buffered output */
}

extern void $Super$$_sys_seek(void);
int $Sub$$_sys_seek(FILEHANDLE fh, long pos)
{
 return -1; /* not supported */
}

extern void $Super$$_sys_flen(void);
long $Sub$$_sys_flen(FILEHANDLE fh)
{
 return -1; /* not supported */
}

extern void $Super$$_sys_exit(void);
long $Sub$$_sys_exit(FILEHANDLE fh)
{
 return -1; /* not supported */
}

With this version of 'retarget.c' linker was satisfied and my program run w/o problem. Maybe this will help you as well.



回答2:

Try by checking if scale_buffer contains any element (scale_buffer.empty()) before calls to .back() and .front(): you are probably reading and writing some garbage, which makes the deque invalid, preparing the ground for a crash when you call push_back()