fprintf函数调用出core
2013-11-26 21:40
232 查看
最近写了一段代码,程序core在了打日志的地方,很诡异。
LOG_FATAL这个宏是自己封装的一个打日志的函数,底层会调用log4cpp的接口,再底层当然就是调用fprintf,vfprintf等。
很普通的一个函数,在代码运行到这里时出core了。
后来自己排查了一下,觉得这个还蛮有意思的一个问题。
问题的原因在于,由于习惯于在64位的系统上写代码,所以习惯于认为%ld就是打印一个64位的整形。
代码中想用%ld打印64位的request.log_id,在64位的系统中没问题。
但在32为的系统中%ld表示long其实只是32位的整形。于是在格式化输出的时候就出现了问题。
假设一个字母x表示一个32位,那么代码中的格式化输出函数在调用的时候内存是这么排的
x x x x
前两个x表示第一个参数,第二个x表示第二个参数,第三个x表示第三个参数。
那么由于%ld是32位的整形,于是在格式化输出的时候,对于第一个输出格式,第一个x被拿走了,
然后在输出第二个格式的时候,拿第二个x,这个时候虽然结果不对,但是程序未必会crash。
但在输出第三个格式的时候,由于第三个格式是字符串,本来应该取第四个x作为字符串的首地址,
但是由于我们在打第一个格式的时候误吧64位认为是32位,导致第三个格式在输出的时候没法取到正确的地址值,
然后由于访问这个非法地址,程序出core。
当然真正的栈帧情况未必就如我所说,但原理是这样的。
LOG_FATAL("[log_id=%ld]sql exception throw, mysql error code = %d, exception %s", request.log_id, e.getErrorCode(), e.what());
LOG_FATAL这个宏是自己封装的一个打日志的函数,底层会调用log4cpp的接口,再底层当然就是调用fprintf,vfprintf等。
很普通的一个函数,在代码运行到这里时出core了。
#0 0x0049fe29 in vfprintf () from /lib/i386-linux-gnu/libc.so.6 #1 0x004c526b in vsnprintf () from /lib/i386-linux-gnu/libc.so.6 #2 0x081a08be in log4cpp::StringUtil::vform(char const*, char*) () #3 0x081942f6 in log4cpp::Category::_logUnconditionally(int, char const*, char*) () #4 0x081944bc in log4cpp::Category::logva(int, char const*, char*) () #5 0x08066b1a in utils::Logger::logva (level=0, stringFormat=0x81b2740 "insert coin earn record failed", arguments=@0xb6965a3c: 0xb6965a54 ",%\033\b|") at src/logger.cpp:86 #6 0x08066b93 in utils::Logger::fatal (stringFormat=0x81b2740 "insert coin earn record failed") at src/logger.cpp:96
后来自己排查了一下,觉得这个还蛮有意思的一个问题。
问题的原因在于,由于习惯于在64位的系统上写代码,所以习惯于认为%ld就是打印一个64位的整形。
代码中想用%ld打印64位的request.log_id,在64位的系统中没问题。
但在32为的系统中%ld表示long其实只是32位的整形。于是在格式化输出的时候就出现了问题。
假设一个字母x表示一个32位,那么代码中的格式化输出函数在调用的时候内存是这么排的
x x x x
前两个x表示第一个参数,第二个x表示第二个参数,第三个x表示第三个参数。
那么由于%ld是32位的整形,于是在格式化输出的时候,对于第一个输出格式,第一个x被拿走了,
然后在输出第二个格式的时候,拿第二个x,这个时候虽然结果不对,但是程序未必会crash。
但在输出第三个格式的时候,由于第三个格式是字符串,本来应该取第四个x作为字符串的首地址,
但是由于我们在打第一个格式的时候误吧64位认为是32位,导致第三个格式在输出的时候没法取到正确的地址值,
然后由于访问这个非法地址,程序出core。
当然真正的栈帧情况未必就如我所说,但原理是这样的。
相关文章推荐
- iOS js oc相互调用(JavaScriptCore 2)
- vue.js 调用iOS原生方法,JavaScriptCore
- iOS js oc相互调用(JavaScriptCore)(二)
- iOS下JS与OC互相调用(四)--JavaScriptCore
- 对象调用corePlot使用技巧及iOS内存优化之道
- iOS js oc相互调用(JavaScriptCore)(二)
- coreseek+php之sphinx扩展安装+php调用示例
- php调用C++扩展库出现段错误 (core dumped)
- EF Core使用SQL调用返回其他类型的查询 ASP.NET Core 2.0 使用NLog实现日志记录 CSS 3D transforms cSharp:use Activator.CreateInstance with an Interface? SqlHelper DBHelper C# Thread.Abort方法真的让线程停止了吗? 注意!你的Thread.Abort方法真
- JS调用OC方法(JavaScriptCore)
- musb_core.c 是usb_general.c 调用进musb模块的核心函数,
- iOS下JS与OC互相调用(四)-->JavaScriptCore
- iOS 基于JavaScriptCore 不等webView加载完毕就交互,网页获取原生内容。 webView的高级用法之JS交互,js与oc的相互调用
- vs2013调用opencv时项目显示 无法启动此程序,因为计算机中丢失opencv_core249.dll。请尝试重新安装改程序
- iOS中使用JavaScriptCore实现Objective-C和JavaScript的相互调用
- iOS webView的高级用法之JS交互,js与oc的相互调用(JavaScriptCore)
- coreseek+php之sphinx扩展安装+php调用示例
- iOS学习Core Data文件操作中调用NSManagedObjectContext类实例save:方法导致程序崩溃
- coreseek+php之sphinx扩展安装+php调用示例
- iOS js oc相互调用(JavaScriptCore)