今天花了点时间调试了ByteArray和String之间的内存泄露。场景如下:
1.TcpServer获取数据以后,直接打包成ByteArray
2.使用ByteArray的时候在转换成String
结果Valgrind出现了下面的提示
==21186== Invalid read of size 1 ==21186== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==21186== by 0x5F394D2: vfprintf (vfprintf.c:1643) ==21186== by 0x5F40F25: printf (printf.c:33) ==21186== by 0x10CF75: _ServerListener::onAccept(int, obotcha::sp<obotcha::_String>, int, obotcha::sp<obotcha::_ByteArray>) (TestTcpServer.cpp:30) ==21186== by 0x52F0D6C: obotcha::_TcpServerThread::run() (TcpServer.cpp:126) ==21186== by 0x527F0B5: obotcha::_Thread::localRun(void*) (Thread.cpp:226) ==21186== by 0x64DC6DA: start_thread (pthread_create.c:463) ==21186== by 0x5FFD88E: clone (clone.S:95) ==21186== Address 0x6cb7a25 is 0 bytes after a block of size 5 alloc'd ==21186== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==21186== by 0x525D57F: obotcha::_ByteArray::_ByteArray(char const*, int) (ByteArray.cpp:56) ==21186== by 0x52F26B7: obotcha::sp<obotcha::_ByteArray> obotcha::createByteArray<char*, int&>(char*&&, int&) (ByteArray.hpp:18) ==21186== by 0x52F0CDF: obotcha::_TcpServerThread::run() (TcpServer.cpp:124) ==21186== by 0x527F0B5: obotcha::_Thread::localRun(void*) (Thread.cpp:226) ==21186== by 0x64DC6DA: start_thread (pthread_create.c:463) ==21186== by 0x5FFD88E: clone (clone.S:95)提示字符串终结符导致的内存问题,对应的代码如下:将ByteArray用来存储数据的char数值,直接传给String的构成早函数在TcpServer获取数据的时候,它是无法判断是否是字符串,所以数据结尾不会有'\0'这个终结符的。但是在字符串使用的时候,如果最后一位不是终结符,那就会出现异常了~~~。出现问题的代码,
void onAccept(int fd,String ip,int port,ByteArray pack) { printf("on accept pack is %s,size is %d \n",pack->toChars(),pack->size()); acceptStr = pack->toString(); acceptCond->notify(); }最如下修改后就没有问题了,toString会重新到std::string中获字符串,且字符串有终结符。
void onAccept(int fd,String ip,int port,ByteArray pack) { printf("on accept pack is %s,size is %d \n",pack->toString()->toChars(),pack->size()); acceptStr = pack->toString(); acceptCond->notify(); }
这回是在string的构造函数的strlen时候出现问题了,好吧。这个和之前问题是一个原因,就是传入的char数据是没有截止符的。
对应代码
String _ByteArray::toString() { return createString(&buff[0],0,_size+1); }呵呵,策略还是一样,扩大一个字节来存放终止符。
String _ByteArray::toString() { //printf("buff buff is %s ,_size is %d\n",buff,_size); char _buff[_size + 1]; memset(_buff,0,_size+1); memcpy(_buff,buff,_size); return createString(&_buff[0],0,_size + 1); }性能上有点慢,哈哈,不过这个是目前能想到的最好的方法。以后再考虑是否有优化空间把。