BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlma_guardingallocator.h
Go to the documentation of this file.
1/// @file bdlma_guardingallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlma_guardingallocator.h -*-C++-*-
8#ifndef INCLUDED_BDLMA_GUARDINGALLOCATOR
9#define INCLUDED_BDLMA_GUARDINGALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlma_guardingallocator bdlma_guardingallocator
15/// @brief Provide a memory allocator that guards against buffer overruns.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlma
19/// @{
20/// @addtogroup bdlma_guardingallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlma_guardingallocator-purpose"> Purpose</a>
25/// * <a href="#bdlma_guardingallocator-classes"> Classes </a>
26/// * <a href="#bdlma_guardingallocator-description"> Description </a>
27/// * <a href="#bdlma_guardingallocator-guard-pages"> Guard Pages </a>
28/// * <a href="#bdlma_guardingallocator-thread-safety"> Thread Safety </a>
29/// * <a href="#bdlma_guardingallocator-usage"> Usage </a>
30/// * <a href="#bdlma_guardingallocator-example-1-diagnosing-buffer-overflow"> Example 1: Diagnosing Buffer Overflow </a>
31/// * <a href="#bdlma_guardingallocator-example-2-allowing-for-maximal-alignment"> Example 2: Allowing for Maximal Alignment </a>
32///
33/// # Purpose {#bdlma_guardingallocator-purpose}
34/// Provide a memory allocator that guards against buffer overruns.
35///
36/// # Classes {#bdlma_guardingallocator-classes}
37///
38/// - bdlma::GuardingAllocator: memory allocator that detects buffer overruns
39///
40/// @see bslma_allocator, bslma_testallocator
41///
42/// # Description {#bdlma_guardingallocator-description}
43/// This component provides a concrete allocation mechanism,
44/// `bdlma::GuardingAllocator`, that implements the `bslma::Allocator` protocol
45/// and adjoins a read/write protected guard page to each block of memory
46/// returned by the `allocate` method. Each returned block is maximally aligned
47/// for the platform. The guard page is located immediately following (subject
48/// to alignment requirements) or immediately preceding the block returned from
49/// `allocate` according to an optionally-supplied constructor argument:
50/// @code
51/// ,------------------------.
52/// ( bdlma::GuardingAllocator )
53/// `------------------------'
54/// | ctor/dtor
55/// V
56/// ,----------------.
57/// ( bslma::Allocator )
58/// `----------------'
59/// allocate
60/// deallocate
61/// @endcode
62/// *WARNING*: Note that this allocator should *not* be used for production use;
63/// it is intended for debugging purposes only. In particular, clients should
64/// be aware that a multiple of the page size is allocated for *each* `allocate`
65/// invocation (unless the size of the request is 0).
66///
67/// Also note that, unlike many other BDE allocators, a `bslma::Allocator *`
68/// cannot be (optionally) supplied upon construction of a `GuardingAllocator`;
69/// instead, a system facility is used that allocates blocks of memory in
70/// multiples of the system page size.
71///
72/// ## Guard Pages {#bdlma_guardingallocator-guard-pages}
73///
74///
75/// A `GuardingAllocator` may be used to debug buffer overflow (or underflow) by
76/// protecting a memory page after (or before) each block of memory returned
77/// from `allocate`. Consequently, certain memory access outside the block
78/// returned to the client will trigger a memory protection fault.
79///
80/// A constructor argument of type `GuardingAllocator::GuardPageLocation`, an
81/// enumeration, determines whether guard pages are located following
82/// (`e_AFTER_USER_BLOCK`) or preceding (`e_BEFORE_USER_BLOCK`) the user block.
83/// If no value is supplied at construction, `e_AFTER_USER_BLOCK` is assumed.
84///
85/// To illustrate, the following diagram shows the memory layout resulting from
86/// an `N`-byte allocation request from a guarding allocator, where `N` is
87/// assumed to be less than or equal to the size of a memory page. Note that
88/// two pages of memory are consumed for each such allocation request:
89/// @code
90/// M - N rounded up to the least multiple of the maximum alignment
91/// A - address of (2-page) block of memory returned by system allocator
92/// U - address returned from 'allocate' to user
93/// G - address of the guard page
94/// PS - page size (in bytes)
95///
96/// e_AFTER_USER_BLOCK
97/// ------------------
98///
99/// [ - - - one memory page - - - | - - - one memory page - - - ]
100/// ---------------------------------------------------------------
101/// | | M bytes | ******* R/W protected ****** |
102/// ---------------------------------------------------------------
103/// ^ ^ ^
104/// A U == G - M G == A + PS
105///
106///
107/// e_BEFORE_USER_BLOCK
108/// -------------------
109///
110/// ---------------------------------------------------------------
111/// | ******* R/W protected ****** | M bytes | |
112/// ---------------------------------------------------------------
113/// ^ ^
114/// A == G U == A + PS
115/// @endcode
116/// Notice that `M`, the distance from the returned address to the start of the
117/// guard page, may be larger than the user requested `N` bytes. See {Example
118/// 2: Allowing for Maximal Alignment}.
119///
120/// ## Thread Safety {#bdlma_guardingallocator-thread-safety}
121///
122///
123/// The `bdlma::GuardingAllocator` class is fully thread-safe (see
124/// @ref bsldoc_glossary ).
125///
126/// ## Usage {#bdlma_guardingallocator-usage}
127///
128///
129/// This section illustrates intended use of this component.
130///
131/// ### Example 1: Diagnosing Buffer Overflow {#bdlma_guardingallocator-example-1-diagnosing-buffer-overflow}
132///
133///
134/// Use of a `bdlma::GuardingAllocator` is indicated, for example, if some code
135/// under development is suspected of having a buffer overrun (or underrun) bug,
136/// and more sophisticated tools that detect such conditions are either not
137/// available, or are inconvenient to apply to the situation at hand.
138///
139/// This usage example illustrates a guarding allocator being brought to bear on
140/// a buffer overrun bug. The bug in question arises in the context of an
141/// artificial data handling class, `my_DataHandler`. This class makes use of a
142/// (similarly artificial) data translation utility that translates chunks of
143/// data among various data styles. In our idealized example, we assume that
144/// the length of the output resulting from some data translation is precisely
145/// determinable from the length of the input data and the respective styles of
146/// the input and the (desired) output. For simplicity, we also assume that
147/// input data comes from a trusted source.
148///
149/// First, we define an enumeration of data styles:
150/// @code
151/// enum my_DataStyle {
152/// e_STYLE_NONE = 0
153/// , e_STYLE_A = 1 // default style
154/// , e_STYLE_AA = 2 // style exactly twice as verbose as 'e_STYLE_A'
155/// // etc.
156/// };
157/// @endcode
158/// Next, we define the (elided) interface of our data translation utility:
159/// @code
160/// /// This `struct` provides a namespace for data translation utilities.
161/// struct my_DataTranslationUtil {
162///
163/// // CLASS METHODS
164///
165/// /// Return the buffer size (in bytes) required to store the result
166/// /// of converting input data of the specified `inputLength` (in
167/// /// bytes), in the specified `inputStyle`, into the specified
168/// /// `outputStyle`. The behavior is undefined unless
169/// /// `0 <= inputLength`.
170/// static int outputSize(my_DataStyle outputStyle,
171/// my_DataStyle inputStyle,
172/// int inputLength);
173///
174/// /// Load into the specified `output` buffer the result of converting
175/// /// the specified `input` data, in the specified `inputStyle`, into
176/// /// the specified `outputStyle`. Return 0 on success, and a
177/// /// non-zero value otherwise. The behavior is undefined unless
178/// /// `output` has sufficient capacity to hold the translated result.
179/// /// Note that this method assumes that `input` originated from a
180/// /// trusted source.
181/// static int translate(char *output,
182/// my_DataStyle outputStyle,
183/// const char *input,
184/// my_DataStyle inputStyle);
185/// };
186/// @endcode
187/// Next, we define `my_DataHandler`, a simple class that makes use of
188/// `my_DataTranslationUtil`:
189/// @code
190/// /// This `class` provides a basic data handler.
191/// class my_DataHandler {
192///
193/// // DATA
194/// my_DataStyle d_inStyle; // style of `d_inBuffer` contents
195/// char *d_inBuffer; // input supplied at construction
196/// int d_inCapacity; // capacity (in bytes) of `d_inBuffer`
197/// my_DataStyle d_altStyle; // alternative style (if requested)
198/// char *d_altBuffer; // buffer for alternative style
199/// bslma::Allocator *d_allocator_p; // memory allocator (held, not owned)
200///
201/// private:
202/// // NOT IMPLEMENTED
203/// my_DataHandler(const my_DataHandler&);
204///
205/// public:
206/// // CREATORS
207///
208/// /// Create a data handler for the specified `input` data, in the
209/// /// specified `inputStyle`, having the specified `inputLength` (in
210/// /// bytes). Optionally specify a `basicAllocator` used to supply
211/// /// memory. If `basicAllocator` is 0, the currently installed
212/// /// default allocator is used. The behavior is undefined unless
213/// /// `0 <= inputLength`.
214/// my_DataHandler(const char *input,
215/// int inputLength,
216/// my_DataStyle inputStyle,
217/// bslma::Allocator *basicAllocator = 0);
218///
219/// ~my_DataHandler();
220/// // Destroy this data handler.
221///
222/// // ...
223///
224/// // MANIPULATORS
225///
226/// /// Generate data for this data handler in the specified
227/// /// `alternateStyle`. Return 0 on success, and a non-zero value
228/// /// otherwise. If `alternateStyle` is the same as the style of data
229/// /// supplied at construction, this method returns 0 with no effect.
230/// int generateAlternate(my_DataStyle alternateStyle);
231///
232/// // ...
233/// };
234/// @endcode
235/// Next, we show the definition of the `my_DataHandler` constructor:
236/// @code
237/// my_DataHandler::my_DataHandler(const char *input,
238/// int inputLength,
239/// my_DataStyle inputStyle,
240/// bslma::Allocator *basicAllocator)
241/// : d_inStyle(inputStyle)
242/// , d_inBuffer(0)
243/// , d_inCapacity(inputLength)
244/// , d_altStyle(e_STYLE_NONE)
245/// , d_altBuffer(0)
246/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
247/// {
248/// BSLS_ASSERT(0 <= inputLength);
249///
250/// void *tmp = d_allocator_p->allocate(inputLength);
251/// bsl::memcpy(tmp, input, inputLength);
252/// d_inBuffer = static_cast<char *>(tmp);
253/// }
254/// @endcode
255/// Next, we show the definition of the `generateAlternate` manipulator. Note
256/// that we have deliberately introduced a bug in `generateAlternate` to cause
257/// buffer overrun:
258/// @code
259/// int my_DataHandler::generateAlternate(my_DataStyle alternateStyle)
260/// {
261/// if (alternateStyle == d_inStyle) {
262/// return 0; // RETURN
263/// }
264///
265/// int altLength = my_DataTranslationUtil::outputSize(alternateStyle,
266/// d_inStyle,
267/// d_inCapacity);
268/// (void)altLength;
269///
270/// // Oops! Should have used 'altLength'.
271/// char *tmpAltBuffer = (char *)d_allocator_p->allocate(d_inCapacity);
272/// int rc = my_DataTranslationUtil::translate(tmpAltBuffer,
273/// alternateStyle,
274/// d_inBuffer,
275/// d_inStyle);
276///
277/// if (rc) {
278/// d_allocator_p->deallocate(tmpAltBuffer);
279/// return rc; // RETURN
280/// }
281///
282/// d_altStyle = alternateStyle;
283/// d_altBuffer = tmpAltBuffer;
284///
285/// return 0;
286/// }
287/// @endcode
288/// Next, we define some data (in `e_STYLE_A`):
289/// @code
290/// const char *input = "AAAAAAAAAAAAAAA@"; // data always terminated with '@'
291/// @endcode
292/// Then, we define a `my_DataHandler` object, `handler`, to process that data:
293/// @code
294/// my_DataHandler handler(input, 16, e_STYLE_A);
295/// @endcode
296/// Note that our `handler` object uses the default allocator.
297///
298/// Next, we request that an alternate data style, `e_STYLE_AA`, be generated by
299/// `handler`. Unfortunately, data in style `e_STYLE_AA` is twice as large as
300/// that in style `e_STYLE_A` making it a virtual certainty that the program
301/// will crash due to the insufficiently sized buffer that is allocated in the
302/// `generateAlternate` method to accommodate the `e_STYLE_AA` data:
303/// @code
304/// int rc = handler.generateAlternate(e_STYLE_AA);
305/// if (!rc) {
306/// // use data in alternate style
307/// }
308/// @endcode
309/// Suppose that after performing a brief post-mortem on the resulting core
310/// file, we strongly suspect that a buffer overrun is the root cause, but the
311/// program crashed in a context far removed from that of the source of the
312/// problem (which is often the case with buffer overrun issues).
313///
314/// Consequently, we modify the code to supply a guarding allocator to the
315/// `handler` object, then rebuild and rerun the program. We have configured
316/// the guarding allocator (below) to place guard pages *after* user blocks.
317/// Note that `e_AFTER_USER_BLOCK` is the default, so it need not be specified
318/// at construction as we have (pedantically) done here:
319/// @code
320/// typedef bdlma::GuardingAllocator GA;
321/// GA guard(GA::e_AFTER_USER_BLOCK);
322///
323/// my_DataHandler handler(input, 16, e_STYLE_A, &guard);
324/// @endcode
325/// With a guarding allocator now in place, a memory fault is triggered when a
326/// guard page is overwritten as a result of the buffer overrun bug. Hence, the
327/// program will dump core in a context that is more proximate to the buggy
328/// code, resulting in a core file that will be more amenable to revealing the
329/// issue when analyzed in a debugger.
330///
331/// ### Example 2: Allowing for Maximal Alignment {#bdlma_guardingallocator-example-2-allowing-for-maximal-alignment}
332///
333///
334/// The requirement that this allocator always return maximally aligned memory
335/// can lead to situations when using `e_AFTER_USER_BLOCK` where there is unused
336/// memory between the end of allocated memory and the first address of the
337/// guard page. If so, small memory overruns (e.g., a single byte) will not
338/// land on the guard page and go undetected. Fortunately, users can often
339/// compensate for this behavior and position their data adjacent to the guard
340/// page.
341///
342/// Suppose one must test a function, `myIntSort`, having the signature and
343/// contract:
344/// @code
345/// /// Efficiently sort in place the values in the specified range
346/// /// `[start .. end - 1]` into ascending order.
347/// void myIntSort(int *begin, int *end);
348/// @endcode
349/// If the `myIntSort` function uses some manner of partitioning algorithm the
350/// implementation will involve considerable pointer arithmetic, recursion,
351/// etc., then a reasonable test concern would be:
352/// @code
353/// // Concerns:
354/// // 1. The implementation never modifies or even reads data outside of
355/// // the given input range.
356/// //
357/// // 2. Some other concern.
358/// //
359/// // 3. Yet another concern.
360/// //
361/// // 4. ...
362/// @endcode
363/// Addressing that test concern is ordinarily challenging. One approach is to
364/// bracket the data for each test with data having a distinctive value (e.g.,
365/// `0x0BADCAFE`) and then check that the test does not corrupt that pattern
366/// (any overwrite being *very* unlikely to preserve the special value). Tests
367/// of reads past the given range are harder to prove. One could argue that
368/// incorporating that data into the sort would corrupt the result but one
369/// cannot prove that it was never accessed. Alternatively, using
370/// `bdlma::GuardingAllocator` provides a stronger proof from a simpler test
371/// case. Thus, our test plan would include:
372/// @code
373/// // Plan:
374/// // 1. Test for range overflow and underflow by positioning test data in
375/// // memory obtained from 'bdlma::GuardingAllocator' objects. Each
376/// // test is run twice, once with the guard page below the test data,
377/// // and again with the guard page above the test data.
378/// @endcode
379/// First, create a set of test data for thoroughly testing all concerns of
380/// `myIntSort`, and a framework for running through those tests:
381/// @code
382/// /// Thoroughly test the `myIntSort` function using a table-driven
383/// /// framework. Note that the testing concerns were listed above.
384/// void testMyIntSort()
385/// {
386/// const bsl::size_t MAX_NUM_INPUTS = 5;
387/// struct {
388/// int d_line;
389/// bsl::size_t d_numInputs;
390/// int d_input[MAX_NUM_INPUTS];
391/// } DATA [] = {
392/// { __LINE__, 1, { 0 } }
393/// , { __LINE__, 2, { 2, 1 } }
394///
395/// // ...
396///
397/// , { __LINE__, 3, { 2, 1, 3 } }
398///
399/// // ...
400///
401/// };
402/// const bsl::size_t NUM_DATA = sizeof DATA / sizeof *DATA;
403///
404/// const int pageSize = myGetPageSize();
405/// assert(myIsPowerOfTwo(pageSize));
406///
407/// for (bsl::size_t ti = 0; ti < NUM_DATA; ++ti) {
408/// const int LINE = DATA[ti].d_line; (void) LINE;
409/// const bsl::size_t NUM_INPUTS = DATA[ti].d_numInputs;
410/// const int *const INPUT = DATA[ti].d_input;
411/// @endcode
412/// Then, create a 'bdlma::GuardingAllocator to that will be used to test for
413/// under-runs of the given range and, for each data point, run the test on data
414/// that will segfault if there is any reference to an address in the page below
415/// `begin`, even by a single byte:
416/// @code
417/// bdlma::GuardingAllocator underRun(
418/// bdlma::GuardingAllocator::e_BEFORE_USER_BLOCK);
419///
420/// const bsl::size_t numBytes = NUM_INPUTS * sizeof(int);
421/// void *block = underRun.allocate(numBytes);
422///
423/// assert(0 == bsls::AlignmentUtil::calculateAlignmentOffset(
424/// block,
425/// pageSize));
426///
427/// bsl::memcpy(block, INPUT, numBytes);
428///
429/// int *begin = static_cast<int *>(block);
430/// int *end = begin + NUM_INPUTS;
431///
432/// myIntSort(begin, end); // TEST
433///
434/// assert(myIsIntSorted(begin, end)); // oracle
435///
436/// underRun.deallocate(block);
437/// @endcode
438/// Notice that, for expository purposes, we confirmed that the `block` is page
439/// aligned.
440///
441/// Next, we will *rerun* the test using data positioned in memory to catch
442/// over-runs of the input range.
443/// @code
444/// bdlma::GuardingAllocator overRun(
445/// bdlma::GuardingAllocator::e_AFTER_USER_BLOCK);
446/// @endcode
447/// The step would be to allocate memory and initialize memory as we did
448/// before. The problem is that memory returned from the
449/// `bdlma::GuardingAllocator` may not abut the following guard page.
450///
451/// Consider a platform where:
452/// * Maximal alignment is 8 bytes.
453/// * `sizeof(int)` is 4 bytes.
454///
455/// For the data point above consisting of 3 values, the required space is 12
456/// bytes (3 * 4) but the maximally aligned address closest to the top of the
457/// returned page is 16 bytes (2 * 8) below the page boundary -- a gap of 4
458/// bytes.
459///
460/// We handle this situation by padding our allocation size to the nearest
461/// multiple of maximal alignment -- 16 bytes in this case. That gives us
462/// allocated memory that abuts the page boundary. This allows us to position
463/// our test data into the allocated memory so that last element fits in the
464/// upper bytes of the returned bytes (i.e., the first 4 bytes of the returned
465/// block are not used by this test).
466///
467/// Now, we calculate the padded allocation size and allocate a block that abuts
468/// the page boundary:
469/// @code
470/// const bsl::size_t paddedSize =
471/// bsls::AlignmentUtil::roundUpToMaximalAlignment(numBytes);
472///
473/// block = overRun.allocate(paddedSize);
474///
475/// int *firstProtectedAddress = static_cast<int *>(
476/// static_cast<void *>(static_cast<char *>(block) + paddedSize));
477///
478/// begin = firstProtectedAddress - NUM_INPUTS;
479/// end = firstProtectedAddress;
480///
481/// assert(0 == bsls::AlignmentUtil::calculateAlignmentOffset(
482/// block,
483/// bsls::AlignmentUtil::BSLS_MAX_ALIGNMENT));
484///
485/// assert(0 == bsls::AlignmentUtil::calculateAlignmentOffset(
486/// begin,
487/// sizeof(int)));
488///
489/// assert(0 == bsls::AlignmentUtil::calculateAlignmentOffset(
490/// end,
491/// pageSize));
492/// @endcode
493/// Notice that again, for purposes of exposition, we have checked the returned
494/// addresses and confirmed:
495/// * The returned address, `block`, is maximally aligned.
496/// * The calculated `begin` is correctly aligned to hold the data value.
497/// * The upper end of the returned block, `end`, is page aligned.
498///
499/// Finally, we load the test data into the carefully positioned memory and
500/// rerun the test:
501/// @code
502/// bsl::memcpy(begin, INPUT, numBytes);
503///
504/// myIntSort(begin, end); // TEST
505/// assert(myIsIntSorted(begin, end)); // oracle
506///
507/// overRun.deallocate(block);
508/// }
509/// }
510/// @endcode
511/// @}
512/** @} */
513/** @} */
514
515/** @addtogroup bdl
516 * @{
517 */
518/** @addtogroup bdlma
519 * @{
520 */
521/** @addtogroup bdlma_guardingallocator
522 * @{
523 */
524
525#include <bdlscm_version.h>
526
527#include <bslma_allocator.h>
528
529#include <bsls_keyword.h>
530#include <bsls_types.h>
531
532
533namespace bdlma {
534
535 // -----------------------
536 // class GuardingAllocator
537 // -----------------------
538
539/// This class defines a concrete thread-safe "guarding" allocator mechanism
540/// that implements the `bslma::Allocator` protocol, and adjoins a
541/// read/write protected guard page to each block of memory returned by the
542/// `allocate` method. The guard page is placed immediately before or
543/// immediately following the block returned from `allocate` according to
544/// the `GuardPageLocation` enumerator value (optionally) supplied at construction.
545///
546/// \note Note that, unlike many other allocators, an allocator
547/// cannot be (optionally) supplied at construction; instead, a system
548/// facility is used that allocates blocks of memory in multiples of the
549/// system page size. Also note that this allocator is intended for
550/// debugging purposes *only*.
551///
552/// See @ref bdlma_guardingallocator
554
555 public:
556 // TYPES
557
558 /// Enumerate the configuration options for `GuardingAllocator` that may
559 /// be (optionally) supplied at construction.
561 e_AFTER_USER_BLOCK, // locate the guard page after the user block
562 e_BEFORE_USER_BLOCK // locate the guard page before the user block
563 };
564
565 private:
566 // DATA
567 GuardPageLocation d_guardPageLocation; // if `e_AFTER_USER_BLOCK`, place
568 // the read/write protected guard
569 // page after the user block;
570 // otherwise, place it before the
571 // block (`e_BEFORE_USER_BLOCK`)
572
573 private:
574 // NOT IMPLEMENTED
576 GuardingAllocator& operator=(const GuardingAllocator&);
577
578 public:
579 // CREATORS
580
581 /// Create a guarding allocator. Optionally specify a `guardLocation`
582 /// indicating where read/write protected guard pages should be placed
583 /// with respect to the memory blocks returned by the `allocate` method.
584 /// If `guardLocation` is not specified, guard pages are placed
585 /// immediately following the memory blocks returned by `allocate`.
586 explicit
588
589 /// Destroy this allocator object.
590 /// \note Note that destroying this allocator
591 /// has no effect on any outstanding allocated memory.
593
594 // MANIPULATORS
595
596 /// Return a newly-allocated maximally-aligned block of memory of the
597 /// specified `size` (in bytes) that has a read/write protected guard
598 /// page located immediately before or after it according to the
599 /// `GuardPageLocation` indicated at construction. If `size` is 0, no memory is allocated and 0 is returned.
600 ///
601 /// \note Note that a multiple of the
602 /// platform's memory page size is allocated for *every* call to this
603 /// method.
605
606 /// Return the memory block at the specified `address` back to this
607 /// allocator. If `address` is 0, this method has no effect.
608 /// Otherwise, the guard page associated with `address` is unprotected and also deallocated.
609 ///
610 /// \pre The behavior is undefined unless `address`
611 /// was returned by `allocate` and has not already been deallocated.
613};
614
615// ============================================================================
616// INLINE DEFINITIONS
617// ============================================================================
618
619 // -----------------------
620 // class GuardingAllocator
621 // -----------------------
622
623// CREATORS
624inline
626: d_guardPageLocation(guardLocation)
627{
628}
629
630} // close package namespace
631
632
633#endif
634
635// ----------------------------------------------------------------------------
636// Copyright 2016 Bloomberg Finance L.P.
637//
638// Licensed under the Apache License, Version 2.0 (the "License");
639// you may not use this file except in compliance with the License.
640// You may obtain a copy of the License at
641//
642// http://www.apache.org/licenses/LICENSE-2.0
643//
644// Unless required by applicable law or agreed to in writing, software
645// distributed under the License is distributed on an "AS IS" BASIS,
646// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
647// See the License for the specific language governing permissions and
648// limitations under the License.
649// ----------------------------- END-OF-FILE ----------------------------------
650
651/** @} */
652/** @} */
653/** @} */
Definition bdlma_guardingallocator.h:553
~GuardingAllocator() BSLS_KEYWORD_OVERRIDE
GuardPageLocation
Definition bdlma_guardingallocator.h:560
@ e_BEFORE_USER_BLOCK
Definition bdlma_guardingallocator.h:562
@ e_AFTER_USER_BLOCK
Definition bdlma_guardingallocator.h:561
void * allocate(bsls::Types::size_type size) BSLS_KEYWORD_OVERRIDE
void deallocate(void *address) BSLS_KEYWORD_OVERRIDE
Definition bslma_allocator.h:545
std::size_t size_type
Definition bslma_allocator.h:593
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition bdlma_alignedallocator.h:278
Definition bdlt_iso8601util.h:707