在使用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坑的更多相关文章

  1. 内存对齐与ANSI C中struct型数据的内存布局 【转】

    转自:http://blog.chinaunix.net/uid-25909619-id-3032209.html 当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将 ...

  2. 内存对齐与ANSI C中struct型数据的内存布局

    当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将如何在内存中放置这些字段?ANSI C对结构体的内存布局有什么要求?而我们的程序又能否依赖这种布局?这些问题或许对不 ...

  3. 浅析内存对齐与ANSI C中struct型数据的内存布局-内存对齐规则

    这些问题或许对不少朋友来说还有点模糊,那么本文就试着探究它们背后的秘密. 首先,至少有一点可以肯定,那就是ANSI C保证结构体中各字段在内存中出现的位置是随它们的声明顺序依次递增的,并且第一个字段的 ...

  4. HotSpot源码分析之C++对象的内存布局

    HotSpot采用了OOP-Klass模型来描述Java类和对象.OOP(Ordinary Object Pointer)指的是普通对象指针,而Klass用来描述对象的具体类型.为了更好理解这个模型, ...

  5. jvm学习记录-对象的创建、对象的内存布局、对象的访问定位

    简述 今天继续写<深入理解java虚拟机>的对象创建的理解.这次和上次隔的时间有些长,是因为有些东西确实不好理解,就查阅各种资料,然后弄明白了才来做记录. (此文中所阐述的内容都是以Hot ...

  6. 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位

    参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...

  7. HotSpot虚拟机对象探秘(对象创建,对象内存布局,对象访问定位)

    以常用的HotSpot虚拟机和JAVA内存区域堆为例,探讨对象的创建,对象的内存布局以及对象的访问定位 一.对象的创建 1)类加载:虚拟机遇到一条new指令时,先检测这个指令的参数能否在常量池中定位到 ...

  8. Java对象的创建、内存布局和访问定位

    在Java运行时数据区中,我们知道了虚拟机内存的概况,本文介绍虚拟机内存中的数据的其它细节,如对象如何创建.如何布局以及如何访问. 基于实用的原则,这里以HotSpot虚拟机和常用的内存区域Java堆 ...

  9. Java对象创建的过程及对象的内存布局与访问定位

    这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...

随机推荐

  1. 个人记录比较好的css样式

    background:#835838;  filter:alpha(opacity=70);-moz-opacity:0.7;opacity:0.8; 设置背景颜色为透明! IE6. IE7.IE8. ...

  2. Bootstrap<基础二十> 标签

    Bootstrap 标签.标签可用于计数.提示或页面上其他的标记显示.使用 class .label 来显示标签,如下面的实例所示: <!DOCTYPE html> <html> ...

  3. MS SQLSERVER中如何快速获取表的记录总数

    在数据库应用的设计中,我们往往会需要获取某些表的记录总数,用于判断表的记录总数是否过大,是否需要备份数据等.我们通常的做法是:select count(*) as c from tableA .然而对 ...

  4. Python Day04

    一.迭代器与生成器: 迭代器(iterator): 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,迭代器的一大优点是不要求事 ...

  5. 在QtCreator 2.1.0 下使用opencv231库加载图片并显示

    在.pro中库连接如上图,具体规则正在学习,注意debug下连接*d.lib.release下链接.lib.没有d的. 如果出现imread不可以加载图片,cvloadImage却可以,则是上面说的连 ...

  6. UDPClient的用法

    UDP_Server: UdpClient receivingUdpClient = ); IPEndPoint RemoteIpEndPoint = ); try { byte[] sdata = ...

  7. 例子:Camera Color Picker Sample (YCbCr->ARGB)

    本例演示了如何从相机preview缓冲区获取YCbCr模块,并且转化为ARGB. 1. 什么是YCbCr y:像素的亮度.以范围从 0 到 255 的字节值形式返回(亮度值始终为正值). cr:像素的 ...

  8. SQLSERVER排查CPU占用高的情况

    SQLSERVER排查CPU占用高的情况 今天中午,有朋友叫我帮他看一下数据库,操作系统是Windows2008R2 ,数据库是SQL2008R2 64位 64G内存,16核CPU 硬件配置还是比较高 ...

  9. html input节点很多 json字符串提交解决方法

    遇到一个页面,38个input节点,页面前端写好的,不太容易改成 js框架 容易操作的样式,只能自己想办法一个一个id获取然后 setvalue getvalue(miniui): 38个一个一个写太 ...

  10. jenkins配置

    自动化测试机器172,27.14.22   IP 一.jenkins要先登录——>点击JCF_Automation——>点击左边配置 二.环境变量赋值就不会把进程杀掉