-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcert-MEM54.cpp
114 lines (98 loc) · 2.75 KB
/
cert-MEM54.cpp
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <array>
#include <cstddef>
#include <iostream>
#include <new>
// MEM54-CPP. Provide placement new with properly aligned pointers to sufficient storage capacity
namespace {
// warning: Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8
// bytes [clang-analyzer-cplusplus.PlacementNew]
void foo()
{
short s{};
long* lp = ::new (&s) long; // diagnostic required
*lp = -1;
}
// Ensures that the long is constructed into a buffer of sufficient size, However:
// warning: Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes
// [clang-analyzer-cplusplus.PlacementNew]
void bar()
{
unsigned char c{}; // Used elsewhere in the function
unsigned char buffer[sizeof(long)];
long* lp = ::new (buffer) long; // diagnostic required
// ...
c = 0x42;
*lp = c;
}
struct S
{
char* data{};
S() : data(new char[16]) { std::cout << "S::S()" << std::endl; }
~S()
{
delete[] data;
data = nullptr;
std::cout << "S::~S()" << std::endl;
}
};
constexpr size_t N = 3;
// This example attempts to allocate sufficient storage of the
// appropriate alignment for the array of objects of S. However:
// warning: Storage provided to placement new is only 32 bytes, whereas the allocated array type
// requires more space for internal needs [clang-analyzer-cplusplus.PlacementNew]
void cookie()
{
alignas(S) unsigned char buffer[sizeof(S) * N];
S* sp = ::new (buffer) S[N];
// ...
// Destroy elements of the array.
for (size_t i = 0; i != N; ++i) {
sp[i].~S(); // diagnostic required
}
}
} // namespace
#if 1
// The amount of overhead required by array new expressions is unspecified but ideally would be
// documented by quality implementations.
# if defined(__clang__) || defined(__GNUG__)
constexpr size_t overhead = sizeof(size_t);
# else
constexpr size_t overhead = 0;
static_assert(overhead, "you need to determine the size of your implementation's array overhead");
# endif
void* operator new[](size_t n, void* p, size_t bufsize)
{
if (n > bufsize) {
throw std::bad_array_new_length();
}
return p;
}
static void good()
{
alignas(S) unsigned char buffer[sizeof(S) * N + overhead];
S* sp = ::new (buffer, sizeof(buffer)) S[N];
// ...
// Destroy elements of the array.
for (size_t i = 0; i != N; ++i) {
sp[i].~S();
}
}
#endif
static void perfect()
{
std::array<S, N> buffer{};
// ...
// Destroy elements of the array.
for (auto& i : buffer) {
i.~S();
} // NOTE: not realy needed! CK
std::cout << "buffer contains still " << buffer.size() << " elements!" << std::endl;
}
int main()
{
foo();
bar();
cookie();
good();
perfect();
}