push_back() 导致程序在进入 main() 之前停止

Posted

技术标签:

【中文标题】push_back() 导致程序在进入 main() 之前停止【英文标题】:push_back() causes program to stop before entering main() 【发布时间】:2013-07-07 01:45:18 【问题描述】:

我正在为我的 STM32F3 Discovery 板使用 c++ 进行开发,并使用 std::deque 作为队列。在尝试调试我的代码后(直接在带有 ST-link 的设备上或在模拟器中),代码最终在断点处停止,甚至在 main() 中输入我的代码之前。但是,SystemInit() 配置板就好了..

我已将此行为追溯到使用 push_back()(和 push_front),因为从代码中将其注释掉可以解决问题。通过disassmebly发现,使用后,执行在断点指令BKPT处停止,恢复执行后不再继续执行。该指令是 _sysopen() 调用的一部分,调用路径为:

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

让我感兴趣的是调用_initio,如果不使用push_back,它就会丢失,因为没有__rt_lib_init_atexit_1。引入 push_back 还使代码大小从 10 kB 变为 34 kB。

这可能是由于某些错误配置造成的,还是我应该尝试其他 IDE?我没有想法。

【问题讨论】:

你能展示一些实际的 C++ 代码吗?删除一行可以防止失败这一事实并不一定意味着错误就在该行中。 @Antonio 当然,看看:gist.github.com/BetaRavener/5957167。取消注释任何 push_back 行都会导致此问题。 scale_buffer的声明呢? 是的,抱歉,更新了 repo,所以现在也有标题了。 【参考方案1】:

我遇到了同样的问题。我了解到这与所谓的“半主机”有关 我应该使用包含定义的项目文件“retarget.c”构建 像“_sys_xxxx()”这样的函数,它们是目标特定的驱动程序级函数 ('retarget.c' 的许多版本是 Keil-MDK 的一部分,也可以在网络上找到)。 所以我做了,但是链接器抛出了类似这样的错误:

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)
...

我通过编辑原始的“retarget.c”解决了这个问题,以便其中定义的函数将 覆盖 Keil-MDK 库中的那些。新的“retargeted.c”在这里:

#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 */

有了这个版本的 'retarget.c' 链接器很满意,我的程序运行没有问题。 也许这对你也有帮助。

【讨论】:

这是继续使用 Keil 时的解决方案,但是由于这个问题,我后来切换到 Eclipse 并使用 ARM 特定的工具链进行构建:launchpad.net/gcc-arm-embedded。 @francek 谢谢。帮助了我。【参考方案2】:

尝试在调用.back().front() 之前检查scale_buffer 是否包含任何元素(scale_buffer.empty()):您可能正在读写一些垃圾,这使得双端队列无效,为您在调用时崩溃做好准备拨打push_back()

【讨论】:

问题是我无法回拨/前拨。如果我愿意(push_back 注释掉)我最终会遇到 HardFault 中断,所以这不是解决方案 @Raven scale_buffer.empty()的返回值是多少? 从逻辑上讲,如果我不推动任何事情,那么是真的(实际上也是如此)。伙计,我不是初学者。 @Raven 我看到的是(例如)scale_buffer.back().second &gt; 0:如果缓冲区为空,那么该检查有何意义? 你是在分析我的概念,而不是解决这个问题。该缓冲区应该每次至少有一个项目(推入构造函数,从不弹出,并不意味着它将永远是同一个项目)。但是,如果 push 不起作用,那么该代码将会有很多这样的问题,但这不是我想要解决的。

以上是关于push_back() 导致程序在进入 main() 之前停止的主要内容,如果未能解决你的问题,请参考以下文章

我的程序在进入main()函数之前退出

C#:在控制台应用程序的 Main 中调用异步方法导致编译失败 [关闭]

Vector::push_back() 给出读取访问冲突

C++程序进入main函数之前,退出main函数之后会做些啥?

vector内存释放 c++

汗,keil 仿真跳不进main