最近阅读leveldb中代码的时候发现,leveldb自己实现了basename
和dirname
的功能,并没有使用glibc
自带的函数,觉得比较奇怪,去查文档然后动手实践后发现原来这里面有个一不小心就会踩到的坑。
man手册中提到,posix版本的glibc实现会改变basename/dirname的参数,而且在使用静态字符串如/usr/
调用时会引起段错误。
自己调试发现,dirname会改变参数,并将最后一个/
改成\0
,如下
执行到dirname
时,原来的这个字符串p
就已经被改变了,并且导致strlen(p)
也会改变。我这里没有复现出段错误的情况,可能又有什么改动把
不过man手册最后也说明了这两个函数的正确用法:
但是这样有内存泄漏的风险,因为strdup
内部调用了malloc
动态分配内存,而且leveldb是使用Slice
这种数据结构来代替字符串的,Slice
并不负责内存管理,所以如果想要在leveldb中使用strdup
调用dirname
就会有内存泄漏的风险,所以作者才自己实现了basename/dirname