当前位置:网站首页>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.
边栏推荐
- Save the image with gaussdb (for redis), and the recommended business can easily reduce the cost by 60%
- [MCU simulation project] external interrupt 0 and 1 control two digit nixie tube to count
- 《opencv学习笔记》-- 边缘检测和canny算子、sobel算子、LapIacian 算子、scharr滤波器
- tf.truncated_ Normal() usage
- The B2B2C multi merchant system has rich functions and is very easy to open
- Leetcode-169. most elements
- 9-20v input peak charging current 3A dual lithium switch type charging chip sc7102
- Opencv learning notes - remapping
- ZK snark: about private key, ring signature, zkksp
- Idea2020.3.1 cannot be opened (double click cannot be opened), but it can be opened through idea.bat.
猜你喜欢

安装VMware报错failed to install the hcmon driver

深度学习之DAT

Find My技术|物联网资产跟踪市场规模达66亿美元,Find My助力市场发展

Kbpc1510-asemi large chip 15A rectifier bridge kbpc1510

Zkevm: summary of zkevm and L1 by Mina's CEO

ACM mm 2022 | end to end multi granularity comparative learning for video text retrieval

深度学习之SuperViT

Mbr3045ct Schottky diode, mbr0100, mbr2060ct diode parameters

Find my technology | the Internet of things asset tracking market has reached US $6.6 billion, and find my helps the market develop

Hurry in!!! Write a number guessing game with dozens of lines of code based on the basic knowledge of C language
随机推荐
【单片机仿真项目】外部中断0和1控制两位数码管进行计数
JS base64编码和解码
E-commerce operator Xiaobai, how to get started quickly and learn data analysis?
waf详解
Opencv learning notes - remapping
[cloud native kubernetes] how to use configmap under kubernetes cluster
Apply for SSL certificate, configure SSL certificate for domain name, and deploy server; Download and installation of SSL certificate
开源许可证的传染性问题浅析
Chinese database oceanbase was selected into the Forrester translational data platform report
Can't the container run? The Internet doesn't have to carry the blame
中国数据库 OceanBase 入选 Forrester Translytical 数据平台报告
Leetcode: 102. Sequence traversal of binary tree
JS Base64 encoding and decoding
微信小程序实现音乐播放器(5)
redux
File upload error: current request is not a multipart request
Dracoo master
WAF details
booking.com缤客上海面经
laravel8 实现接口鉴权封装使用JWT