追踪内存分配 重载全局new和delete实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include "../src/include/local.h" #define ps(str) std::cout << str << std::endl struct AllocationMetrics { uint32_t TotalAllocated = 0 ; uint32_t TotalFreed = 0 ; uint32_t CurrentUsage () { return TotalAllocated - TotalFreed; } }; AllocationMetrics s_AllocationMetrics;struct Object { int x, y, z; };void * operator new (size_t size) { s_AllocationMetrics.TotalAllocated += size; std::cout << "Allocating " << size << " bytes\n" ; return malloc (size); }void operator delete (void * memory,size_t size) { s_AllocationMetrics.TotalFreed += size; free (memory); }void PrintMemoryUsage () { std::cout << "Memory Usage: " << s_AllocationMetrics.CurrentUsage () << " bytes\n" ; }int main () { PrintMemoryUsage (); std::string name = "Cherno" ; PrintMemoryUsage (); { std::unique_ptr<Object> obj = std::make_unique <Object>(); PrintMemoryUsage (); } PrintMemoryUsage (); std::cin.get (); }
简单区分左右值 注意:std::string& name此参数仅能接收左值,但是加上const,即const std::string &name 此参数既能接收左值又能接收右值,编译器构造一个临时变量(左值),作为参数传递给函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include "../src/include/local.h" #define ps(str) std::cout << str << std::endl void PrintName (std::string&& name) { std::cout << "[Rvalue] " << name << std::endl; }void PrintName (const std::string& name) { std::cout << "[Lvalue] " << name << std::endl; }int main () { int i = 10 ; std::string firstName = "yan" ; std::string lastName = "Chernikov" ; std::string fullName = firstName + lastName; PrintName (fullName); PrintName (firstName + lastName); std::cin.get (); }
使用静态代码分析工具PVS-Studio 安装后,在Vs菜单栏->扩展->PVS->check-current-file,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> struct Entity { };Entity* LoadEntity () { return nullptr ; }int main () { Entity* entity = LoadEntity (); if (entity) { } const char * string = "Hello" ; char * buffer = new char [strlen (string)]; memcpy (buffer,string,strlen (string)); uint32_t width = 800 , height = 600 ; uint32_t * buffer = new uint32_t [width*height]; for (uint32_t y = 0 ; y < height; y++) { for (uint32_t x = 0 ; x < width; y++) { buffer[x + y * width] = 0 ; } } std::cin.get (); }
上面代码明显错误/优化点:
entity永远为nullptr,分支只能降低程序执行速度
buffer大小分配有问题
第2层for循环有问题
Argument Evaluation Order(参数求值顺序)
PVS报错:unspecified behavior,The order of argument evaluation is not defined for 'PrintSum' function,Consider inspecting the 'value' variable
c++标准没有指定函数定义的参数的求值顺序
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> void PrintSum (int a, int b) { std::cout << a << " + " << b << " = " << (a + b) << std::endl; }int main () { int value = 0 ; PrintSum (value++,value++); std::cin.get (); }
MSVC 开启c++17选项
Debug模式
Release模式
的结果都是1+0=1,并且编译没有warning
clang 10.0.0 clang++ prog.cc -Wall -Wextra -std=c++17
1 2 3 4 prog.cc:10:16: warning: multiple unsequenced modifications to 'value' [-Wunsequenced] PrintSum(value++,value++); ^ ~~ 1 warning generated.
执行结果:0+1=1,貌似是从左到右执行
gcc 9.3.0 g++ prog.cc -Wall -Wextra -I/opt/wandbox/boost-1.73.0/gcc-9.3.0/include -std=c++17
1 2 3 4 5 prog.cc: In function 'int main()': prog.cc:10:24: warning: operation on 'value' may be undefined [-Wsequence-point] 10 | PrintSum(value++,value++); | ~~~~~^~prog.cc:10:24: warning: operation on 'value' may be undefined [-Wsequence-point]
执行结果:1+0=1,和MSVC的结果一样