<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[Snooda]]></title> 
<link>http://www.snooda.com/index</link> 
<description><![CDATA[Snooda's Blog]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[Snooda]]></copyright>
<item>
<link>http://www.snooda.com/read/337</link>
<title><![CDATA[libcurl和openssl的冲突和资源释放问题-curl_global_cleanup]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Thu, 25 Sep 2014 16:59:38 +0000</pubDate> 
<guid>http://www.snooda.com/read/337</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;最近程序发现了个奇葩现象，即从文件载入的证书链用openssl校验是通过的，而用curl远程获取的就校验失败，错误码7。而这些内容写入文件在下一次程序启动时载入校验，又是成功的。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;排查了各种内存泄露、不可见字符的可能性后。突然想起来是不是libcurl静态链接了openssl跟主程序动态链接的打架。查看后发现libcurl未静态链接openssl。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 不过这也是一个启示。想起来既然curl也用到了openssl，那么它在最后cleanup的时候会不会把全局的openssl数据结构给释放掉。<br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 尝试了一下，果然好了。原来我在一个函数里开头调用curl_global_init，结尾调用curl_global_cleanup。这样的话在程序结束时就会释放openssl的全局数据结构。导致后续调用证书校验报错。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 不过openssl也不够友好，报证书签名错误，让人很难联想到是初始化问题。<br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不过aes加密部分并不受这个影响。<br/>Tags - <a href="http://www.snooda.com/tags/openssllibcurl/" rel="tag">openssllibcurl</a>
]]>
</description>
</item><item>
<link>http://www.snooda.com/read/302</link>
<title><![CDATA[malloc、calloc、memset与free等内存操作的速度]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Tue, 29 May 2012 16:55:28 +0000</pubDate> 
<guid>http://www.snooda.com/read/302</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;一直对内存操作的速度没有数值概念，只泛泛的知道memset影响效率，反复分配释放内存影响效率，具体速度如何，从来没试过，今天试验了一下。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;写了个程序，分配一个指针数组，挨个分配内存，然后挨个释放。使用的是一台2核16g内存的虚拟机。gcc版本3.4.2<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;先是分配了1w个100字节块，发现5ms以内即可完成。<br/>&nbsp;&nbsp;&nbsp;&nbsp;然后扩大到500字节块，速度没什么变化。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;然后分配100w个字节块，平均需要270ms左右。<br/>&nbsp;&nbsp;&nbsp;&nbsp;字节块扩大的2k左右，大概5s完成。<br/>&nbsp;&nbsp;&nbsp;&nbsp;扩大到5k左右，大概12s左右。<br/>&nbsp;&nbsp;&nbsp;&nbsp;以上数据均为malloc+memset数据和calloc数据，两者不相上下。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;只malloc不memset，大概能缩短20%左右，可见memset对速度还是有一定影响的，不过对于性能要求不是那么严苛的程序，设置一下提高程序稳定性也是值得的。避免某变量忘记初始化出现野值的问题。<br/><br/><br/><br/><br/>Tags - <a href="http://www.snooda.com/tags/%25E5%2586%2585%25E5%25AD%2598/" rel="tag">内存</a>
]]>
</description>
</item><item>
<link>http://www.snooda.com/read/294</link>
<title><![CDATA[printf空指针NULL的问题]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Wed, 16 May 2012 09:52:37 +0000</pubDate> 
<guid>http://www.snooda.com/read/294</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;今天发现程序中有几个地方在没有校验指针为NULL的时候进行了打印日志操作，在字符串处理函数中使用NULL指针不是什么好事，研究了一下，发现在一些的linux发行版中，printf("%s",NULL)会打印一个“（NULL）”，而在solaris中则会出core，windows下也没有问题。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;可见不同的c库对于这个行为的实现不太一致。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;使用中还是要尽量避免这种用法，不过每次打日志前都要判断指针情况确实比较恶。<br/><br/><br/><br/><br/>
]]>
</description>
</item><item>
<link>http://www.snooda.com/read/275</link>
<title><![CDATA[lua_tolstring导致调用lua_next时的lua PANIC问题]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Sat, 28 Apr 2012 09:49:01 +0000</pubDate> 
<guid>http://www.snooda.com/read/275</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;前两天在用lua_next遍历一个lua表的时候遇到了：PANIC: unprotected error in call to Lua API (invalid key to 'next')&nbsp;&nbsp;仔细检查了下代码和堆栈信息，发现没有问题，但为什么会说遍历失败呢？<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;找到文档看了下，原来lua_tolstring只支持number和string类型，但是对于number类型，在取值后也会转换其在表中的实际内容为string，而我遍历的表是使用默认自增索引作为key的，这样对key调用这个函数会导致key变成字符串，因而遍历有问题。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;如果表的key不一定是string，而又要用lua_tolstring获取它的值，那么建议先在栈上复制一份，然后对于复制的值进行获取。<br/><br/><br/><br/><br/><br/><br/>Tags - <a href="http://www.snooda.com/tags/lua/" rel="tag">lua</a>
]]>
</description>
</item><item>
<link>http://www.snooda.com/read/260</link>
<title><![CDATA[c程序中变量在循环内部还是外部声明的问题]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Mon, 09 Apr 2012 07:40:27 +0000</pubDate> 
<guid>http://www.snooda.com/read/260</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;忘记之前从哪看过的一个文章说不要在for、while等循环内声明变量，因为每次都会重复分配空间，很慢。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;今天发现一个模块把变量声明都放到while里面了，看了下代码没有发现必须声明在里面的原因，于是开始怀疑是不是声明在内外是差不多的。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;于是测试了一下：<br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content"><br/>int main() &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;int i = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for(;i < 10000000; i++) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int b;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b++;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 1;<br/>&#125;<br/></div></div><br/><br/>使用gcc 编译，把int b放在循环内外试了试，用time ./a.out查看执行时间，发现用时基本相同。<br/>添加-O2优化选项，执行时间均缩减到之前的1/3，内外两种方式时间依然相同。<br/>定义了一个struct实验了下，结果相同<br/>也就是说栈上元素的操作不必纠结于变量声明于何处。<br/><br/>尝试了下堆上元素操作，在预料之内：时间差距巨大，因为重复分配释放内存。<br/><br/>所以对于栈上元素，声明放在循环里和循环外是一样的。堆上元素不同，需注意。<br/><br/>另，仍然需要注意一些计算操作需要放在循环外，比如求大小之类的，避免循环的每个周期重复计算。<br/><br/><br/>原因猜测：1， cpu对栈操作有优化，速度非常快。<br/>2，编译器的基本优化中会优化（gcc没有使用-O参数时仍会优化）<br/>具体原因待深究
]]>
</description>
</item><item>
<link>http://www.snooda.com/read/259</link>
<title><![CDATA[静态库和动态库编译链接时的依赖检查]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Thu, 05 Apr 2012 11:48:04 +0000</pubDate> 
<guid>http://www.snooda.com/read/259</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;今天编译lua程序时发现总是报缺少dlopen和pow之类的，需要手动加-lm -dl才行。感觉有点奇异，按我的理解来说使用静态库是不需要考虑依赖的。仔细研究了下，发现很多误区。<br/>&nbsp;&nbsp;&nbsp;&nbsp;首先用静态库编译出的可执行文件是不考虑库依赖的，但并不代表用静态库时也不需要考虑。静态库在编译时是不检查函数是否被实现的，也就是说只需要.h即可。<br/>&nbsp;&nbsp;&nbsp;&nbsp;其次，静态库和动态库其实区别很大，静态库只是编译出.o的一个打包的文件，而动态库添加了链接信息。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;这样的话静态库还有一个特性，就是在静态库中可以调用一些预留接口，而把这些接口留待以后实现。<br/>Tags - <a href="http://www.snooda.com/tags/%25E7%25BC%2596%25E8%25AF%2591%25E4%25BE%259D%25E8%25B5%2596/" rel="tag">编译依赖</a>
]]>
</description>
</item><item>
<link>http://www.snooda.com/read/243</link>
<title><![CDATA[由strcm参数为NULL看编译器优化]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Tue, 14 Feb 2012 10:29:49 +0000</pubDate> 
<guid>http://www.snooda.com/read/243</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;今天程序出了一个core，是strcmp的时候有一个参数没有判断为NULL导致的，当我编写了一个小程序：<br/><br/><div class="quote"><div class="quote-title">引用</div><div class="quote-content">#include <stdio.h> <br/>int main() <br/>&#123; <br/>strcmp(NULL, "“); <br/>return 1; <br/>&#125;</div></div><br/>测试的时候发现程序跑的毫无问题。<br/>编译参数是gcc -g -O0，没有开任何优化。<br/><br/>gdb进去后发现strcmp根本没有被执行，改成int a = strcmp(NULL, "");后，出core了。<br/><br/>看来编译器默认还是提供一定优化的。<br/><br/>另外需要注意strcmp不会检查参数（效率考虑），所以需要自己检查。<br/>Tags - <a href="http://www.snooda.com/tags/strcmp/" rel="tag">strcmp</a> , <a href="http://www.snooda.com/tags/%25E7%25BC%2596%25E8%25AF%2591%25E5%2599%25A8%25E4%25BC%2598%25E5%258C%2596/" rel="tag">编译器优化</a>
]]>
</description>
</item><item>
<link>http://www.snooda.com/read/241</link>
<title><![CDATA[由一个小概率出core看函数声明的重要性]]></title> 
<author>snooda &lt;admin@snooda.com&gt;</author>
<category><![CDATA[c程序设计]]></category>
<pubDate>Sat, 14 Jan 2012 15:39:58 +0000</pubDate> 
<guid>http://www.snooda.com/read/241</guid> 
<description>
<![CDATA[ 
	&nbsp;&nbsp;&nbsp;&nbsp;最近程序遇到一个小概率出core的bug，高压力下大概10分钟左右就会出core，gdb查看发现一个指针高四字节被置0xffffffff了，低四字节正常。<br/>&nbsp;&nbsp;&nbsp;&nbsp;该指针是局部变量，存放在栈上，排除了线程间同步互斥写坏数据的可能。<br/>&nbsp;&nbsp;&nbsp;&nbsp;该指针前后变量均正常，都是指针，排除了写越界的可能。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;通过日志查看，在返回该指针的函数返回前，指针正常，返回后高四字节即被置0xffffffff了。推断应该是函数返回的过程中遭到了破坏。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;但不知道为什么返回的过程中会出错，请教了下组内高工，高人就是高人，一听问题描述就表示应该是函数声明的问题。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;原来，在调用另一个so文件中的函数时，如果没有该函数的声明，由于从该so的符号表里可以找到函数，所以编译可以通过，但gcc会把这个函数返回值按默认的int处理，这种情况下，32位机编译的程序是没问题的，但64位机上指针是8字节，导致高四字节数据丢失。但返回的指针超过int值域时，高四字节数据丢失，导致指针被破坏。<br/><br/>&nbsp;&nbsp; 所以函数声明还是不可或缺的。<br/>Tags - <a href="http://www.snooda.com/tags/core/" rel="tag">core</a> , <a href="http://www.snooda.com/tags/%25E5%2587%25BD%25E6%2595%25B0%25E5%25A3%25B0%25E6%2598%258E/" rel="tag">函数声明</a>
]]>
</description>
</item>
</channel>
</rss>