📄 testmemleak.cpp
字号:
} void class9() { check("class A\n" "{\n" "public:\n" " int * p;\n" " A();\n" " ~A();\n" "};\n" "\n" "A::A()\n" "{ p = new int; }\n" "\n" "A::~A()\n" "{ delete (p); }\n", true); ASSERT_EQUALS("", errout.str()); } void throw1() { check("void foo()\n" "{\n" " char *str = new char[10];\n" " if ( ! abc )\n" " throw 123;\n" " delete [] str;\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:5]: (error) Memory leak: str\n"), errout.str()); } void throw2() { check("void foo()\n" "{\n" " char *str = 0;\n" " try\n" " {\n" " str = new char[100];\n" " if ( somecondition )\n" " throw exception;\n" " delete [] str;\n" " }\n" " catch ( ... )\n" " {\n" " delete [] str;\n" " }\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void linux_list_1() { check("struct AB\n" "{\n" " int a;\n" " int b;\n" "};\n" "void foo()\n" "{\n" " struct AB *ab = new AB;\n" " func(&ab->a);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void sizeof1() { check("void f()\n" "{\n" " struct s_t s1;\n" " struct s_t cont *p = &s1;\n" " struct s_t *s2;\n" "\n" " memset(p, 0, sizeof(*p));\n" "\n" " s2 = (struct s_t *) malloc(sizeof(*s2));\n" "\n" " if (s2->value != 0)\n" " return;\n" "\n" " free(s2);\n" "\n" " return;\n" "}\n"); std::string err(errout.str()); ASSERT_EQUALS(std::string("[test.cpp:12]: (error) Memory leak: s2\n"), err); } void realloc1() { check("void foo()\n" "{\n" " char *a = (char *)malloc(10);\n" " a = realloc(a, 100);\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:5]: (error) Memory leak: a\n"), errout.str()); } void realloc2() { check("void foo()\n" "{\n" " char *a = (char *)malloc(10);\n" " a = (char *)realloc(a, 100);\n" " free(a);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void assign() { check("void foo()\n" "{\n" " char *a = (char *)malloc(10);\n" " a = 0;\n" " free(a);\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Memory leak: a\n"), errout.str()); check("void foo()\n" "{\n" " char *a = (char *)malloc(10);\n" " char *p = a;\n" " free(p);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); check("void foo()\n" "{\n" " char *a = (char *)malloc(10);\n" " char *p = a + 1;\n" " free(p);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); check("void foo()\n" "{\n" " char *a = (char *)malloc(10);\n" " a += 10;\n" " free(a - 10);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); check("void foo()\n" "{\n" " char *a = (char *)malloc(10);\n" " a = (void *)a + 10;\n" " free(a - 10);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); check("void foo()\n" "{\n" " char *a = new char[100];\n" " list += a;\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void varid() { check("void foo()\n" "{\n" " char *p = malloc(100);\n" " {\n" " char *p = 0;\n" " delete p;\n" " }\n" " free(p);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void cast1() { check("void foo()\n" "{\n" " char *a = reinterpret_cast<char *>(malloc(10));\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Memory leak: a\n"), errout.str()); } void cast2() { check("void foo()\n" "{\n" " char *a = malloc(10);\n" " free((void *)a);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void cast3() { check("void foo()\n" "{\n" " char *a = malloc(10);\n" " free(reinterpret_cast<void *>(a));\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void structmember1() { check("void f()\n" "{\n" " struct ABC *abc = new ABC;\n" " abc->a = new char[100];\n" " delete abc;\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:5]: (error) Memory leak: abc.a\n"), errout.str()); } void dealloc_use_1() { check("void f()\n" "{\n" " char *s = new char[100];\n" " delete [] s;\n" " p = s;\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:5]: (error) Using 's' after it is deallocated / released\n"), errout.str()); } void dealloc_use_2() { check("void f()\n" "{\n" " char *str;\n" " free(str);\n" " foo(&str);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void dealloc_use_3() { check("void foo()\n" "{\n" " char *str = 0;\n" " free(str);\n" " f1(&str);\n" " f2(str);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void dealloc_use_4() { check("static void ReadDir(DIR *d)\n" "{\n" " DIR *subdir = OpenDir();\n" " ReadDir( subdir );\n" " closedir(subdir);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void dealloc_use_5() { check("void foo()\n" "{\n" " char *str = 0;\n" " free(str);\n" " char c = str[10];\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:5]: (error) Using 'str' after it is deallocated / released\n"), errout.str()); } void dealloc_use_6() { check("void foo()\n" "{\n" " char *str = 0;\n" " free(str);\n" " printf(\"free %x\", str);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void dealloc_use_7() { check("void foo()\n" "{\n" " char *str = new char[10];\n" " delete [] str;\n" " str[10] = 0;\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:5]: (error) Using 'str' after it is deallocated / released\n"), errout.str()); } void freefree1() { check("void foo()\n" "{\n" " char *str = malloc(100);\n" " free(str);\n" " free(str);\n" "}\n"); ASSERT_EQUALS(std::string("[test.cpp:5]: (error) Deallocating a deallocated pointer: str\n"), errout.str()); } void freefree2() { check("void foo()\n" "{\n" " FILE *fd = fopen(\"test.txt\", \"wb\");\n" " fprintf(fd, \"test\");\n" " fclose(fd);\n" "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } void strcat_result_assignment() { check("void foo()\n" "{\n" " char *p = malloc(10);\n" " p[0] = 0;\n" " p = strcat( p, \"a\" );\n" " free( p );\n" " return 0;\n" "}"); ASSERT_EQUALS(std::string(""), errout.str()); } void all1() { check("void foo()\n" "{\n" " Fred *f = new Fred;\n" "}\n", false); ASSERT_EQUALS(std::string(""), errout.str()); check("void foo()\n" "{\n" " Fred *f = new Fred;\n" "}\n", true); ASSERT_EQUALS(std::string("[test.cpp:4]: (all) Memory leak: f\n"), errout.str()); } void malloc_constant_1() { check("void foo()\n" "{\n" " int *p = malloc(3);\n" " free(p);\n" "}\n", false); ASSERT_EQUALS(std::string("[test.cpp:3]: (error) The given size 3 is mismatching\n"), errout.str()); } void unknownFunction1() { check("void foo()\n" "{\n" " int *p = new int[100];\n" " if (abc)\n" " {\n" " delete [] p;\n" " ThrowException();\n" " }\n" " delete [] p;\n" "}\n"); ASSERT_EQUALS("", errout.str()); } void unknownFunction2() { check("void foo()\n" "{\n" " int *p = new int[100];\n" " if (abc)\n" " {\n" " delete [] p;\n" " ThrowException();\n" " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:9]: (error) Memory leak: p\n", errout.str()); } void unknownFunction3() { check("void foo()\n" "{\n" " int *p = new int[100];\n" " ThrowException();\n" "}\n"); ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: p\n", errout.str()); } void checkvcl(const char code[], const char _autoDealloc[]) { // Tokenize.. Tokenizer tokenizer; { std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); } tokenizer.setVarId(); tokenizer.simplifyTokenList(); // Clear the error buffer.. errout.str(""); // Check for memory leaks.. Settings settings; settings._debug = true; settings._showAll = true; { std::istringstream istr(_autoDealloc); settings.autoDealloc(istr); } CheckMemoryLeakClass checkMemoryLeak(&tokenizer, settings, this); checkMemoryLeak.CheckMemoryLeak(); } void vcl1() { checkvcl("void Form1::foo()\n" "{\n" " TEdit *Edit1 = new TEdit(this);\n" "}\n", "TEdit\n"); ASSERT_EQUALS("", errout.str()); } void vcl2() { checkvcl("class Fred\n" "{\n" "private:\n" " TButton *button;\n" "public:\n" " Fred();\n" "};\n" "\n" "Fred::Fred()\n" "{\n" " button = new TButton(this);\n" "}\n", "TButton\n"); ASSERT_EQUALS("", errout.str()); }};REGISTER_TEST(TestMemleak)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -