如何优雅的写C++代码 Obotcha介绍(Valgrind内存泄露调试三)

mac2022-06-30  102

  今天花了点时间调试了ByteArray和String之间的内存泄露。场景如下:

  1.TcpServer获取数据以后,直接打包成ByteArray

  2.使用ByteArray的时候在转换成String

问题1:

  结果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(); }

 

问题2:

==27890== Thread 5: ==27890== Invalid read of size 1 ==27890== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==27890== by 0x5A61506: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25) ==27890== by 0x522F234: obotcha::_String::_String(char const*, int, int) (String.cpp:264) ==27890== by 0x525E030: obotcha::sp<obotcha::_String> obotcha::createString<char*, int, int>(char*&&, int&&, int&&) (String.hpp:29) ==27890== by 0x525DC54: obotcha::_ByteArray::toString() (ByteArray.cpp:195) ==27890== by 0x10CF69: _ServerListener::onAccept(int, obotcha::sp<obotcha::_String>, int, obotcha::sp<obotcha::_ByteArray>) (TestTcpServer.cpp:30) ==27890== by 0x52F0CC0: obotcha::_TcpServerThread::run() (TcpServer.cpp:126) ==27890== by 0x527F009: obotcha::_Thread::localRun(void*) (Thread.cpp:226) ==27890== by 0x64DB6DA: start_thread (pthread_create.c:463) ==27890== by 0x5FFC88E: clone (clone.S:95) ==27890== Address 0x6cb6735 is 0 bytes after a block of size 5 alloc'd ==27890== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==27890== by 0x525D57F: obotcha::_ByteArray::_ByteArray(char const*, int) (ByteArray.cpp:56) ==27890== by 0x52F260B: obotcha::sp<obotcha::_ByteArray> obotcha::createByteArray<char*, int&>(char*&&, int&) (ByteArray.hpp:18) ==27890== by 0x52F0C33: obotcha::_TcpServerThread::run() (TcpServer.cpp:124) ==27890== by 0x527F009: obotcha::_Thread::localRun(void*) (Thread.cpp:226) ==27890== by 0x64DB6DA: start_thread (pthread_create.c:463) ==27890== by 0x5FFC88E: clone (clone.S:95)

这回是在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); }

性能上有点慢,哈哈,不过这个是目前能想到的最好的方法。以后再考虑是否有优化空间把。

最新回复(0)