根据内存布局定位的一个fastdfs坑
在使用fastdfs时,编写数据上传代码时,遇到一个坑。最终根据指针对应的内存布局定位到一个其client API的一个坑,值得记录一下。
具体是在 tracker_connect_server() 这个API上,其是一个宏,具体定义如下
#define tracker_connect_server(pTrackerServer, err_no) \
tracker_connect_server_ex(pTrackerServer, g_fdfs_connect_timeout, err_no)
tracker_connect_server_exs 声明如下
ConnectionInfo *tracker_connect_server_ex(ConnectionInfo *pTrackerServer, const int connect_timeout, int *err_no);
在tracker_proto.c中实现,其返回值将在后面数据上传操作中的链接句柄。
当配置不使用连接池的时候,连接操作成功时,会将 pTrackerServer 参数原样返回,一般使用者会习惯性地保存该指针句柄供后用。我自己仿照着范例代码使用,结果就掉坑里了。
如此设计实现,就极易产生勿用,如下:
当 tracker_connect_server_ex() 的 pTrackerServer 参数传递的对象,后续被销毁之后,用户是不知道刚才通过返回值拿到的指针句柄指向的对象是已经不复存在的。
后续继续使用该已经失效的指针句柄进行数据上传操作时,结果就不可预知了。
实际上在其工程test目录下的范例代码 dfs_func.c 中, upload_file() 函数 pTrackerServer 参数就传递了一个栈上的临时对象,但其在 upload_file() 中立即使用返回值的指针句柄调用 storage_upload_by_filebuff1() 进行数据上传,所以对应返回值指针句柄指向的对象,在此过程中都一直有效,而没有造成问题。
但自己就没有这么幸运了。我类似地仿照 upload_file() 给 tracker_connect_server() 传递了一个栈上的临时对象时,拿到其返回值做保存之后,将从当前调用函数返回了,
后续使用刚才保存的指针句柄调用 storage_do_upload_file1() 进行数据上传操作,总是出现下面的错误打印
[2016-03-05 17:46:26] ERROR - file: storage_client.c, line: 933, send data to storage server :0 fail, errno: 88, error info: Socket operation on non-socket
于是就开始了一番debug,可从 tracker_connect_server() 调用返回的地方,一路确认到调用 storage_do_upload_file1() 的地方,该指针句柄值都没有发生变化,但其指向的内存却被异常地清零了,一时见鬼了!后来在 gdb 中对给 storage_do_upload_file1() 传递的前两个参数值 print 了一把,发现了一点端倪,如下
(gdb) p ((struct fastdfs_priv*)&dfs[1])->tracker_conn
$4 = (ConnectionInfo *) 0x613150
(gdb) p ((struct fastdfs_priv*)&dfs[1])->storage_conn
$5 = (ConnectionInfo *) 0x7fffffffe4e0
(gdb)
根据地址区间,很明显 tracker_conn 指向的内存在堆上,而 storage_conn 指向的内存在栈里!这就奇了怪,storage_conn 值源头是来自 tracker_connect_server() 啊,难道其给我返回了一个栈上的临时对象地址?其作者应该不会犯这种弱智错误吧?去看了 tracker_connect_server_ex() 的代码之后,顿时吐血!太坑了吧!作者自己难道没想过上面的这些问题么?而且还在范例代码中,这么用?明显误导人么??!!!
知道原因之后,立即将 tracker_connect_server() 第一个参数传递的对象改为不是临时的后,问题解决!
刚才的问题,之所以能发现突破点,还是根据指针值对应的内存布局来确定的。这又一次说明了内存等的相关的基础知识是非常重要的!!!
根据内存布局定位的一个fastdfs坑的更多相关文章
- 内存对齐与ANSI C中struct型数据的内存布局 【转】
转自:http://blog.chinaunix.net/uid-25909619-id-3032209.html 当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将 ...
- 内存对齐与ANSI C中struct型数据的内存布局
当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将如何在内存中放置这些字段?ANSI C对结构体的内存布局有什么要求?而我们的程序又能否依赖这种布局?这些问题或许对不 ...
- 浅析内存对齐与ANSI C中struct型数据的内存布局-内存对齐规则
这些问题或许对不少朋友来说还有点模糊,那么本文就试着探究它们背后的秘密. 首先,至少有一点可以肯定,那就是ANSI C保证结构体中各字段在内存中出现的位置是随它们的声明顺序依次递增的,并且第一个字段的 ...
- HotSpot源码分析之C++对象的内存布局
HotSpot采用了OOP-Klass模型来描述Java类和对象.OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象的具体类型.为了更好理解这个模型, ...
- jvm学习记录-对象的创建、对象的内存布局、对象的访问定位
简述 今天继续写<深入理解java虚拟机>的对象创建的理解.这次和上次隔的时间有些长,是因为有些东西确实不好理解,就查阅各种资料,然后弄明白了才来做记录. (此文中所阐述的内容都是以Hot ...
- 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位
参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...
- HotSpot虚拟机对象探秘(对象创建,对象内存布局,对象访问定位)
以常用的HotSpot虚拟机和JAVA内存区域堆为例,探讨对象的创建,对象的内存布局以及对象的访问定位 一.对象的创建 1)类加载:虚拟机遇到一条new指令时,先检测这个指令的参数能否在常量池中定位到 ...
- Java对象的创建、内存布局和访问定位
在Java运行时数据区中,我们知道了虚拟机内存的概况,本文介绍虚拟机内存中的数据的其它细节,如对象如何创建.如何布局以及如何访问. 基于实用的原则,这里以HotSpot虚拟机和常用的内存区域Java堆 ...
- Java对象创建的过程及对象的内存布局与访问定位
这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...
随机推荐
- 一种效率更高的for循环
var i,array=[]; for(i=array.length;i--;) { //处理代码 } 1.for循环中使用更少的变量 2.逐步减至0,这样会更快,因为同0比较比同数组的长度比较,或同 ...
- Excel
EXCEL Excel2003中如何复制多个分开的单元格而不复制中间的内容
- petset翻译
Terminology 通过这个文档,你将会看到一些术语,有时候他们在别的地方交叉使用,这可能会引起一些困惑.这一节的 是帮助你理清楚他们. Node: 一个简单的虚拟或物理机在你的一个k ...
- 用Runtime.getRuntime().exec()需要注意的地方
有时候我们可能需要调用系统外部的某个程序,此时就可以用Runtime.getRuntime().exec()来调用,他会生成一个新的进程去运行调用的程序. 此方法返回一个java.lang.Proce ...
- (转)Oracle 在Drop表时的Cascade Constraints
Oracle 在Drop表时的Cascade Constraints 假设A为主表(既含有某一主键的表),B为从表(即引用了A的主键作为外键).则当删除A表时,如不特殊说明,则 drop table ...
- Bootstrap 模态框在用户点击背景空白处时会自动关闭
问题: Bootstrap 模态框在用户点击背景空白处时,会自动关闭. 解决方法: 在HTML页面中编写模态框时,在div初始化时添加属性 aria-hidden=”true” data-backdr ...
- Apache RewriteRule
1.Rewirte主要的功能就是实现URL的跳转,它的正则表达式是基于Perl语言.可基 于服务器级的(httpd.conf)和目录级的 (.htaccess)两种方式.如果要想用到rewrite模块 ...
- LR一个简单的流程
1.录制脚本 2.回放脚本 :回放前的运行时设置:run_time_seting F4 关联设置(动态值) 日志分析 3.脚本的增强: 添加事物(计时) 参数化(模拟真实的用户行为) 内容检查.回 ...
- fatal error: 'XCTest/XCTest.h' file not found
这个报错在几个方面.第一,它导致XCTedt依赖您的应用程序.框架,它只是在Xcode中可用.第二,你使用绝对路径,这并不保证是相同的从Mac Mac(例如,如果你安装了多个版本的Xcode). 这里 ...
- Log4J日志管理类使用详解 (转)
一.前言: log4j 是一个开放源码项目,是广泛使用的以Java编写的日志记录包.由于log4j出色的表现, 当时在log4j完成时,log4j开发组织曾建议sun在jdk1.4中用log4j取代j ...