最近做的程序中需要字符做一些转换,例如将1变成01会用到如下代码:
wstringstream wstrStream; wstrStream<<setfill(L"0")<<setw(2)<<1; wcout<<wstrStream.str()<<endl;
这段代码在PC环境下没有问题。
但是前两行代码运行在嵌入式环境中,造成了程序跑飞,本人也是无语了。
下面是单步运行时的源码及汇编代码:
basic_ios.h:452: _M_streambuf(0), _M_ctype(0), _M_num_put(0), _M_num_get(0) 200EA3D8 E28D6E51 ADD r6,sp,#0x510 200EA3DC E2866008 ADD r6,r6,#0x8 200EA3E0 E2860034 ADD r0,r6,#0x34 200EA3E4 EB08BFA0 BL 2031A26C std::ios_base::ios_base 200EA3E8 E59F3540 LDR r3,200EA930 200EA3EC E58D354C STR r3,[sp,#0x54C] 200EA3F0 E3A01000 MOV r1,#0x0 200EA3F4 E58D15BC STR r1,[sp,#0x5BC] 200EA3F8 E58D15C0 STR r1,[sp,#0x5C0] 200EA3FC E5CD15C4 STRB r1,[sp,#0x5C4] 200EA400 E58D15C8 STR r1,[sp,#0x5C8] 200EA404 E58D15CC STR r1,[sp,#0x5CC] 200EA408 E58D15D0 STR r1,[sp,#0x5D0] 200EA40C E58D15D4 STR r1,[sp,#0x5D4] istream:582: : _M_gcount(streamsize(0)) 200EA410 E3043710 MOVW r3,#0x4710 200EA414 E34231A6 MOVT r3,#0x21A6 200EA418 E5937008 LDR r7,[r3,#0x8] 200EA41C E58D7518 STR r7,[sp,#0x518] 200EA420 E1A0B006 MOV r11,r6 200EA424 E1A06007 MOV r6,r7 200EA428 E593A00C LDR r10,[r3,#0x0C] 200EA42C E536300C LDR r3,[r6,#-0x0C]! 200EA430 E78BA003 STR r10,[r11,r3] 200EA434 E58D151C STR r1,[sp,#0x51C] istream:583: { this->init(0); } 200EA438 E59D3518 LDR r3,[sp,#0x518] 200EA43C E513000C LDR r0,[r3,#-0x0C] 200EA440 E08B0000 ADD r0,r11,r0 200EA444 EBFF3AC5 BL 200B8F60 std::basic_ios<wchar_t,std::char_traits<wchar_t>_>::init 200EA448 EA000001 B 200EA454 200EA44C E1A04000 MOV r4,r0 200EA450 EA000042 B 200EA560 ostream:362: { this->init(0); } 200EA454 E3043710 MOVW r3,#0x4710 200EA458 E34231A6 MOVT r3,#0x21A6 200EA45C E5932010 LDR r2,[r3,#0x10] 200EA460 E58D2520 STR r2,[sp,#0x520] 200EA464 E28D8E52 ADD r8,sp,#0x520 200EA468 E512200C LDR r2,[r2,#-0x0C] 200EA46C E5933014 LDR r3,[r3,#0x14] 200EA470 E7883002 STR r3,[r8,r2] 200EA474 E59D3520 LDR r3,[sp,#0x520] 200EA478 E513000C LDR r0,[r3,#-0x0C] 200EA47C E0880000 ADD r0,r8,r0 200EA480 E3A01000 MOV r1,#0x0 200EA484 EBFF3AB5 BL 200B8F60 std::basic_ios<wchar_t,std::char_traits<wchar_t>_>::init 200EA488 EA000006 B 200EA4A8 200EA48C E1A04000 MOV r4,r0 istream:102: { _M_gcount = streamsize(0); } 200EA490 E58D7518 STR r7,[sp,#0x518] 200EA494 E5963000 LDR r3,[r6] 200EA498 E78BA003 STR r10,[r11,r3] 200EA49C E3A03000 MOV r3,#0x0 200EA4A0 E58D351C STR r3,[sp,#0x51C] 200EA4A4 EA00002D B 200EA560 istream:799: : __istream_type(), __ostream_type() { } 200EA4A8 E3043710 MOVW r3,#0x4710 200EA4AC E34231A6 MOVT r3,#0x21A6 200EA4B0 E5932004 LDR r2,[r3,#0x4] 200EA4B4 E58D2518 STR r2,[sp,#0x518] 200EA4B8 E28D7E51 ADD r7,sp,#0x510 200EA4BC E2877008 ADD r7,r7,#0x8 200EA4C0 E512200C LDR r2,[r2,#-0x0C] 200EA4C4 E5933018 LDR r3,[r3,#0x18] 200EA4C8 E7873002 STR r3,[r7,r2] sstream:511: : __iostream_type(), _M_stringbuf(__m) 200EA4CC E59F3460 LDR r3,200EA934 200EA4D0 E58D3518 STR r3,[sp,#0x518] 200EA4D4 E2832028 ADD r2,r3,#0x28 200EA4D8 E58D254C STR r2,[sp,#0x54C] 200EA4DC E2833014 ADD r3,r3,#0x14 200EA4E0 E58D3520 STR r3,[sp,#0x520] streambuf:442: _M_buf_locale(locale()) 200EA4E4 E59F344C LDR r3,200EA938 200EA4E8 E58D3524 STR r3,[sp,#0x524] 200EA4EC E3A03000 MOV r3,#0x0 200EA4F0 E58D3528 STR r3,[sp,#0x528] 200EA4F4 E58D352C STR r3,[sp,#0x52C] 200EA4F8 E58D3530 STR r3,[sp,#0x530] 200EA4FC E58D3534 STR r3,[sp,#0x534] 200EA500 E58D3538 STR r3,[sp,#0x538] 200EA504 E58D353C STR r3,[sp,#0x53C] 200EA508 E2870028 ADD r0,r7,#0x28 200EA50C EB08CA16 BL 2031CD6C std::locale::locale sstream:93: : __streambuf_type(), _M_mode(__mode), _M_string() 200EA510 E59F3424 LDR r3,200EA93C 200EA514 E58D3524 STR r3,[sp,#0x524] 200EA518 E3A03018 MOV r3,#0x18 200EA51C E58D3544 STR r3,[sp,#0x544] basic_string.h:2150: : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { } 200EA520 E30369F0 MOVW r6,#0x39F0 200EA524 E34A6051 MOVT r6,#0x0A051 basic_string.h:255: : _Alloc(__a), _M_p(__dat) { } 200EA528 E59F3410 LDR r3,200EA940 200EA52C E58D3548 STR r3,[sp,#0x548] sstream:512: { this->init(&_M_stringbuf); } 200EA530 E2870034 ADD r0,r7,#0x34 200EA534 E287100C ADD r1,r7,#0x0C 200EA538 EBFF3A88 BL 200B8F60 std::basic_ios<wchar_t,std::char_traits<wchar_t>_>::init 200EA53C EA00000D B 200EA578 200EA540 E1A04000 MOV r4,r0 200EA544 E28D0E52 ADD r0,sp,#0x520 200EA548 E2800004 ADD r0,r0,#0x4 200EA54C EBFF3C6E BL 200B970C std::basic_stringbuf<wchar_t,std::char_traits<wchar_t>,... 200EA550 E28D0E51 ADD r0,sp,#0x510 200EA554 E2800008 ADD r0,r0,#0x8 200EA558 E59F13E4 LDR r1,200EA944 200EA55C EBFF3782 BL 200B836C std::basic_iostream<wchar_t,std::char_traits<wchar_t>_>... basic_ios.h:272: ~basic_ios() { } 200EA560 E28D0E66 ADD r0,sp,#0x660 200EA564 E59F33C4 LDR r3,200EA930 200EA568 E5203114 STR r3,[r0,#-0x114]! 200EA56C EB08BEFB BL 2031A160 std::ios_base::~ios_base 200EA570 E1A00004 MOV r0,r4 200EA574 EB095C69 BL 20341720 __cxa_end_cleanup iomanip:189: __os.fill(__f._M_c); 200EA578 E59D3520 LDR r3,[sp,#0x520] 200EA57C E513A00C LDR r10,[r3,#-0x0C] 200EA580 E088A00A ADD r10,r8,r10 basic_ios.h:362: if (!_M_fill_init) 200EA584 E5DA3078 LDRB r3,[r10,#0x78] 200EA588 E3530000 CMP r3,#0x0 200EA58C 1A00000A BNE 200EA5BC basic_ios.h:440: { return __check_facet(_M_ctype).widen(__c); } 200EA590 E59A0080 LDR r0,[r10,#0x80] basic_ios.h:48: if (!__f) 200EA594 E3500000 CMP r0,#0x0 200EA598 1A000000 BNE 200EA5A0 basic_ios.h:49: __throw_bad_cast(); 200EA59C EB08BB6B BL 20319350 std::__throw_bad_cast //error locale_facets.h:287: { return this->do_widen(__c); } 200EA5A0 E5903000 LDR r3,[r0] 200EA5A4 E5933028 LDR r3,[r3,#0x28] 200EA5A8 E3A01020 MOV r1,#0x20 200EA5AC E12FFF33 BLX r3 basic_ios.h:364: _M_fill = this->widen(" "); 200EA5B0 E58A0074 STR r0,[r10,#0x74] basic_ios.h:365: _M_fill_init = true; 200EA5B4 E3A03001 MOV r3,#0x1 200EA5B8 E5CA3078 STRB r3,[r10,#0x78] basic_ios.h:383: _M_fill = __ch; 200EA5BC E3A03030 MOV r3,#0x30 200EA5C0 E58A3074 STR r3,[r10,#0x74] ios_base.h:660: _M_width = __wide; 200EA5C4 E28D0E51 ADD r0,sp,#0x510 200EA5C8 E2800008 ADD r0,r0,#0x8 200EA5CC E59D3520 LDR r3,[sp,#0x520] 200EA5D0 E513300C LDR r3,[r3,#-0x0C] 200EA5D4 E0803003 ADD r3,r0,r3 200EA5D8 E3A02002 MOV r2,#0x2 200EA5DC E5832010 STR r2,[r3,#0x10] test.cpp:144: wstrStream<<setfill(L"0")<<setw(2)<<1; 200EA5E0 E2800008 ADD r0,r0,#0x8 200EA5E4 E3A01001 MOV r1,#0x1 200EA5E8 EB0002FC BL 200EB1E0 std::basic_ostream<wchar_t,std::char_traits<wchar_t>_>:...
开始时候就是为wstrStream分配内存吧,怎么走到这一句就崩了呢?
200EA59C EB08BB6B BL 20319350 std::__throw_bad_cast //error
注意下面这句还没执行。
wstrStream<<setfill(L"0")<<setw(2)<<1;
所以本人又做了两次测试:
1.只定义一个变量
wstringstream wstrStream;
没问题!
2.不使用setfill 和setw
wstringstream wstrStream; wstrStream<<1;
也没问题!
所以问题应该出在setfill 和setw函数上,但是根据汇编报错的位置,不是setfill 和setw报的错啊!本人懵逼了。
也许本人汇编分析的不对,请各位帮看看!
解决方案
5
嵌入式不清楚
很多嵌入式没有操作系统
直接裸机跑
这样的话,假如主程序不是循环(一个几乎永远运行的循环)
那么由于程序跑飞的原因,最终也会形成循环执行
只是不知道你这里是啥情况,嵌入式用上了C++
应该跑在操作系统上了吧
这个操作系统有控制台么?
很多嵌入式没有操作系统
直接裸机跑
这样的话,假如主程序不是循环(一个几乎永远运行的循环)
那么由于程序跑飞的原因,最终也会形成循环执行
只是不知道你这里是啥情况,嵌入式用上了C++
应该跑在操作系统上了吧
这个操作系统有控制台么?
5
wstringstream 改成 wostringstream 试试?
10
理解和讨论之前请先学会怎么样观察!
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……
对学习编程者的忠告:
多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!
不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建全部,然后在IDE中运行。(一般人本人不告诉他!)
单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。
VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或在某行按F9设了断点后按F5执行停在该断点处的时候。
Windows:
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处,看不懂时双击下一行,直到能看懂为止。
Linux:
进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件例如‘core.1234’
使用命令
gdb 运行程序名 core或core.数字
进入gdb然后使用bt命令
可以查看进程意外退出前函数调用的堆栈,内容为从上到下列出对应从里层到外层的函数调用历史。
假如进程意外退出不产生core文件,参考“ulimit -c core文件最大块大小”命令
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……
对学习编程者的忠告:
多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!
不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建全部,然后在IDE中运行。(一般人本人不告诉他!)
单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。
VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或在某行按F9设了断点后按F5执行停在该断点处的时候。
Windows:
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处,看不懂时双击下一行,直到能看懂为止。
Linux:
进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件例如‘core.1234’
使用命令
gdb 运行程序名 core或core.数字
进入gdb然后使用bt命令
可以查看进程意外退出前函数调用的堆栈,内容为从上到下列出对应从里层到外层的函数调用历史。
假如进程意外退出不产生core文件,参考“ulimit -c core文件最大块大小”命令
20
嵌入式,没有环境,无法验证了。
PC上是没有问题的。
这个功能不行了就本人实现?
也不是很麻烦。根据长度插入补足字符就好了。
PC上是没有问题的。
这个功能不行了就本人实现?
也不是很麻烦。根据长度插入补足字符就好了。