Memcheck
只能检测出两种错误类型:
-
use of illegal addresses
-
use of undefined values
这两种错误类型,足以应对大多数的情况。下面针对这两种类型出现的错误进行解释。
Illegal read / Illegal write errors
Invalid read of size 1
at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x4F50018: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
by 0x109C71: main (argparse_.cc:53)
这表示程序在读取/写入一段Memcheck
应该操作的内存。本错误提示中,程序在地址0x109C71
读取了一个字节,在程序中的地址是 main (argparse_.cc:53)
。
Use of uninitialised values
- 程序中的局部变量没有被初始化就使用了
malloc
的内存块的内容,在没有写入任何内容之前就使用了,C++
中是new
运算符。
比如:
char* chr = static_cast<char*>(::malloc(sizeof(char)));
std::cout<<"chr:" <<*chr<<std::endl;
::free(chr);
由于没有对::malloc
分配的内存进行初始化就使用了,就会导致这个错误。
Conditional jump or move depends on uninitialised value(s)
at 0x5250A65: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1241)
by 0x5244976: fwrite (iofwrite.c:39)
by 0x4F4FCB3: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
by 0x4F4FF57: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
by 0x108A10: main (in /home/szz/Study/SystemProgram/Cpp/unitest/src/a.out)
其他的的使用没有初始化的变量也会产生这个问题。
int main(int argc, char const* argv[]) {
int x;
printf("x=%d.\n",x);
}
Illegal frees
即,free/delete
次数多于malloc/new
。
比如对于代码:
char* chr = static_cast<char*>(::malloc(sizeof(char)));
std::cout<<"chr:" <<*chr<<std::endl;
::free(chr);
::free(chr);
return 0;
用valgrind
得到的错误报告就有Invalid free() / delete / delete[] / realloc()
:
Invalid free() / delete / delete[] / realloc()
at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x108A3D: main (in /home/szz/Study/SystemProgram/Cpp/unitest/src/a.out)
Address 0x5b7dc80 is 0 bytes inside a block of size 1 free'd
Mismatched free() / delete / delete []
- 释放内存和分配的方式不一致。比如
new[]
分配的,而采用delete
- 使用
new/malloc
分配而采用free/delete
释放。
比如代码:
char* chr = new char[10];
delete chr;
产生的错误如下:
Mismatched free() / delete / delete []
at 0x4C3123B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x108817: main (in /home/szz/Study/SystemProgram/Cpp/unitest/src/a.out)
Address 0x5b7dc80 is 0 bytes inside a block of size 10 alloc'd
at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x108802: main (in /home/szz/Study/SystemProgram/Cpp/unitest/src/a.out)
正确的方式
- If allocated with malloc, calloc, realloc, valloc or memalign, you must deallocate with free
- If allocated with new[], you must deallocate with delete[]
- If allocated with new, you must deallocate with delete
Passing system call parameters with inadequate read/write permissions
当发送系统调用时,Memcheck
会检测系统调用的所有参数。
- 如果是内核从用户应用程序
buffer
中读取数据,Memcheck
会检测:1)buffer
地址是否是可寻址的,2)这个数据是否是可读的。 - 如果是从内核向用户程序中的
buffer
写入数据,Memcheck
会检测:1)buffer
地址是否是可寻址的。
完成这个系统调用后,Memcheck更新其管理信息,以准确反映由系统调用引起的内存许可权的任何更改。
比如:
char* arr = (char*)::malloc(10);
::write(STDOUT_FILENO, arr, 10);
检测就会发生错误:
Syscall param write(buf) points to uninitialised byte(s)
at 0x52D5154: write (write.c:27)
by 0x1087FC: main (in /home/szz/Study/SystemProgram/Cpp/unitest/src/a.out)
Address 0x5b7dc80 is 0 bytes inside a block of size 10 alloc'd
at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x1087E2: main (in /home/szz/Study/SystemProgram/Cpp/unitest/src/a.out)
因此程序试图向将未初始化的内存arr
写入标准输出,这个未初始化的数据是不可写的。
Overlapping source and destination blocks
即目的和源地址存在重复,主要是 memcpy()
, strcpy()
, strncpy()
, strcat()
和strncat()
等函数。