当前位置:网站首页>Operator new, operator delete supplementary handouts
Operator new, operator delete supplementary handouts
2022-07-26 03:53:00 【GarryLau】
1. understand new-handler
When operator new When a memory allocation requirement cannot be met , It throws an exception ( Of course you can nothrow edition ), When operator new Before throwing an exception to reflect an unmet memory requirement , It will first call an error handling function new-handler( Of course, it must be called first set_new_handler.
for example :
#include <new>
void outOfMem() {
std::cerr << "Unable to satifsy request for memory\n";
std::abort();
}
int main() {
std::set_new_handler(outOfMem);
int *pBigDataArray = new int[100000000L];
}
For more information, please refer to references 1 Of Clause 49: understand new-handler act (Understand the behavior of the new-handler)P240.
2. understand new and delete Reasonable replacement time of
Understand when it makes sense to replace new and delete.
Replace the standard library operator new、operator delete Common reasons :
2.1 Used to detect errors in use .
a. take new The resulting memory delete Failure to do so will result in memory leaks (memory leaks);
b. stay new The resulting memory is processed multiple times delete Can lead to uncertain behavior ;
c. Data due to various programming errors ”overruns“( The write point is after the allocated block ) or ”underruns“( The write point is before the start of the allocated block ).【 If you customize one operator new, You can over allocate memory , With extra space ( Before or after the customer's block ) Place specific byte patterns】.operator delete It is possible to check whether the above signature is intact , If no, it means that at some point in the allocation area overrunns or underruns,operator delete Sure log Facts and pointers to problems ( Personal understanding , Can be in operator delete When checking the specific byte patterns Has it changed ).
2.2 To enhance effectiveness
compiler ( Standard library ) Provided operator new and operator delete Take the golden mean , You need to be moderately friendly to every task , But not the best performance for any particular person . Self defined operator new and operator delete Performance is better than the default version , Custom version It's quite fast , Sometimes it's much faster , and Less memory required , Save up to 50%. For some programs, the standard library operator new and operator delete Replacing it with a customized version is one of the ways to achieve significant performance improvements .
2.3 To collect usage statistics
Using custom operator new and operator delete You should know how the developed software uses dynamic memory . such as , How about the size distribution of allocation blocks ? How about the life distribution ? They tend to take FIFO( fifo ) Sequence or LIFO( Last in, first out ) Order or random order to distribute and return ? Whether their application patterns change over time , That is, the software has different allocation in different execution stages / Return form ? What is the maximum dynamic allocation required at any time ? Use customization operator new and operator delete Easy to collect this information .
#pragma once
#include <new>
#include <cstdlib>
#include <stdexcept>
#include <iostream>
static const int kSignature = 0xDEADBEEF;
void* operator new(size_t size) {
if(void* mem = malloc(size + 2 * sizeof(int))) {
*((int*)mem) = kSignature;
*((int*)((unsigned char*)mem + sizeof(int) + sizeof(unsigned char)*size)) = kSignature;
std::cout << "malloc successfully" << std::endl;
return (unsigned char*)mem + sizeof(int);
}
else {
throw std::bad_alloc();
}
}
void operator delete(void *mem) noexcept {
std::cout << "Entering self-define operator delete...\n";
if(mem) {
/* Be careful , Under normal circumstances operator delete There is no way to verify overuns, Because you don't know the memory size, you can't add an offset Maybe you would say add an extra parameter , for example ,void operator delete(void *mem, int extra) noexcept But this form will only be called when there is an exception in the constructor */
// Of course, there are other methods to verify overuns, For example delete Perform active verification by offsetting according to the size of the requested memory
if((*(int*)((unsigned char*)mem - sizeof(int)) == kSignature)) {
free((unsigned char*)mem - sizeof(int));
std::cout << "free successfully" << std::endl;
}
else{
std::cerr << "memory underruns!!!" << std::endl;
}
}
}
auto test_operator_new_main() -> void {
std::cout << "testing operator new & operator delete for overruns&underruns..." << std::endl;
int *ptr = new int;
*((unsigned char*)ptr - 2) = 'P';
delete ptr;
std::cout << "------------------------------" << std::endl;
}
compiler cmake -G "Visual Studio 15 2017" -A x64 .. Result ( This running result meets the design expectation ):
testing operator new & operator delete for overruns&underruns...
malloc successfully
Entering self-define operator delete...
memory underruns!!!
------------------------------
compiler cmake -G "MinGW Makefiles" .. Result ( This operation result does not meet the design expectation ):
testing operator new & operator delete for overruns&underruns...
malloc successfully
The results show that the results are different under different compilers ,"MinGW Makefiles" Should call the standard library from time to time operator delete, The customized version is not used .
2.4 To detect usage errors
Such as 2.3 Section description .
2.5 To collect usage statistics of dynamically allocated memory
Such as 2.3 Section description .
2.6 In order to increase the speed of distribution and return
( Standard library ) Universal distributors tend to ( Although not always ) Slower than custom allocators , Especially when the custom allocator is specially designed for a specific type of object .
2.7 In order to reduce the extra space overhead caused by the default memory manager
General purpose memory managers tend to ( Although not always ) Not only is it slower than a custom allocator , And often uses more memory , Because they often have some extra overhead on each allocation block .
2.8 To compensate for the non optimal parity in the default allocator
stay x86 Architecturally double If it is 8-byte Alignment is the fastest access , But the compiler comes with operator new Dynamic allocation is not guaranteed double take 8 Byte alignment . here , Will default to operator new Replace with a 8 Byte version can greatly improve program efficiency .
2.9 In order to cluster related objects
If some data are often used together , And you hope to minimize the frequency of page missing exceptions when processing these data , So create a heap It makes sense , Use new and delete Of placement Version allows these data to be clustered on as few memory pages as possible .
2.10 In order to obtain unconventional behavior
Sometimes I hope operator new and operator delete Do what the compiler default version doesn't do . For example, custom operator delete Overwrite the returned content with 0.
3. To write new and delete We need to stick to the routine
3.1 Handle 0 bytes Memory application for
C++ Regulations , Even if the customer requires 0 bytes,operator new You also have to return a legal pointer , So heavy load operator new It should be able to handle 0 byte apply .
In response 0 bytes Before applying for memory, you need to introduce EBO,Empty Base Optimization Blank base class optimization . That is, if the base class is empty , Then the size of its subclass is the size of subclass members .
#include <iostream>
#include <typeinfo>
#include <stdio.h>
namespace test_ebo {
class Empty{
};
class Empty2{
};
class Derived1 : public Empty {
};
class Derived2 : public Empty {
private:
char c_;
};
class Derived3 : public Empty {
private:
int i_;
};
class MultipleDerived : public Derived1 {
};
class DerivedMultiBase : public Empty, public Empty2 {
};
auto main() -> int {
std::cout << "testing test_ebo......\n" << std::endl;
std::cout << "sizeof(Empty): " << sizeof(Empty) << std::endl; // 1
std::cout << "sizeof(Derived1): " << sizeof(Derived1) << std::endl; // 1
std::cout << "sizeof(Derived2): " << sizeof(Derived2) << std::endl; // 1
std::cout << "sizeof(Derived3): " << sizeof(Derived3) << std::endl; // 4
std::cout << "sizeof(MultipleDerived): " << sizeof(MultipleDerived) << std::endl; // 1
std::cout << "sizeof(DerivedMultiBase): " << sizeof(DerivedMultiBase) << std::endl; // 1
std::cout << typeid(MultipleDerived).name() << std::endl;
std::cout << typeid(DerivedMultiBase).name() << std::endl;
return 0;
}
}
cmake -G "MinGW Makefiles" .. compile , Output :
sizeof(Empty): 1
sizeof(Derived1): 1
sizeof(Derived2): 1
sizeof(Derived3): 4
sizeof(MultipleDerived): 1
sizeof(DerivedMultiBase): 1
N8test_ebo15MultipleDerivedE
N8test_ebo16DerivedMultiBaseE
Processing applications 0 bytes An example of :
void* operator new(std::size_t size) {
if(0 == size) {
size = 1; // take 0-byte As 1-byte apply
}
while(true) {
// Try to assign size bytes
if( Distribution succeeded ) {
return( Pointer to the allocated memory )
}
// Allocation failed : Find out the current new-handling function
new_handler globalHandler = set_new_handler(0);
set_new_handler(globalHandler);
if(globalHandler)(*globalHandler)();
else throw std::bad_alloc();
}
}
3.2 Be careful operator new Will be inherited by subclasses
class Base {
public:
static void* operator new(size_t size);
};
class Derived: public Base {
}; // hypothesis Derived Not a statement operator new
Derived* p = new Derived; // Called here Base::operator new
If Base exclusive operator new Not designed for Base Subclasses of ( In fact, this is often the case ), Then you should use the standard library when applying for subclass object memory operator new, Like this :
void* Base::operator new(size_t size) {
if(size != sizeof(Base)) {
// If the size is not the size of the base class, use the operator new
return ::operator new(size);
}
// ...... // Or deal with it here
}
3.3 more operator new For details, please move Reference And hands-on experiments
Reference
- Scott Meyers. Effective C++ Improve program and design 55 Specific practices ( The third edition ), Electronic industry press ,2011.
边栏推荐
- 基于JSP实现网上商城系统
- 想要做好软件测试,可以先了解AST、SCA和渗透测试
- Save the image with gaussdb (for redis), and the recommended business can easily reduce the cost by 60%
- 资深报表开发经验总结:明白这一点,没有做不好的报表
- 触觉智能分享-RK3568在景区导览机器人中的应用
- Navicat连接云端服务器上的MySQL数据库
- Can't the container run? The Internet doesn't have to carry the blame
- Apply for SSL certificate, configure SSL certificate for domain name, and deploy server; Download and installation of SSL certificate
- Div setting height does not take effect
- PHP < => spacecraft operator (combined comparator)
猜你喜欢

Testing is not valued? Senior: you should think in another position

5年1.4W倍,NFT OG 的封神之路|Web3专栏

php 查找 session 存储文件位置的方法

用GaussDB(for Redis)存画像,推荐业务轻松降本60%

深度学习之SuperViT

Analysis on the infectious problem of open source license

基于SSM选课信息管理系统

The convolution kernel is expanded to 51x51, and the new CNN architecture slak counterattacks the transformer

zkEVM:MINA的CEO对zkEVM和L1相关内容的总结
![[stl] priority queue priority_ queue](/img/79/d13913cbb9d98f936a9501633b38bf.png)
[stl] priority queue priority_ queue
随机推荐
在 Istio 服务网格内连接外部 MySQL 数据库
Basic line chart: the most intuitive presentation of data trends and changes
开源许可证的传染性问题浅析
WAF details
Idea2020.3.1 cannot be opened (double click cannot be opened), but it can be opened through idea.bat.
基于Caffe ResNet-50网络实现图片分类(仅推理)的实验复现
中国数据库 OceanBase 入选 Forrester Translytical 数据平台报告
Data elements
booking.com缤客上海面经
触觉智能分享-RK3568在景区导览机器人中的应用
Can't the container run? The Internet doesn't have to carry the blame
MySQL索引失效场景以及解决方案
通用测试用例写作规范
第十八章:2位a~b进制中均位奇观探索,指定整数的 3x+1 转化过程,指定区间验证角谷猜想,探求4份黑洞数,验证3位黑洞数
Matlab paper illustration drawing template issue 39 - stairs
Moco V2: further upgrade of Moco series
[MCU simulation project] external interrupt 0 and 1 control two digit nixie tube to count
One stop monitoring of the software and hardware infrastructure of the whole university, and Suzhou University replaces PostgreSQL with time series database
Tactile intelligent sharing-rk3568 application in scenic spot navigation robot
Chinese database oceanbase was selected into the Forrester translational data platform report