Restrict Object Allocation to Specific Memory Types

Restrict Object Allocation to Specific Memory Types

C++ inherited from C its three memory storage types: automatic storage (also called stack memory), static storage for namespace-scope objects and local static objects, and the free-store(also called the heap), which is used for dynamically-allocated objects.

In many cases, this diversity complicates things. For example, in mobile platforms such as Symbian, free-store objects are mandatory due to the system’s tiny stack size. Likewise, garbage collectors and smart-pointers require that objects be allocated on the free-store exclusively. But in other cases, you want to ensure that objects are neverallocated on the free-store. The following sections show how to enforce such class-specific memory usage policies.

How do you ensure that objects of a certain class are allocated on the free-store exclusively? Similarly, how can you encourage automatic and static storage types for a given class while disabling free-store allocation?

Enforce memory allocation policies by controlling the access type of a class’s member functions.

Disabling Static and Automatic Objects
Smart pointer classes such as auto_ptrmust own objects that were allocated on the free-store. Alas, the compiler doesn’t detect violations of this restriction:

#include #include int main (){ std::ofstream myfile;std::auto_ptr file_ptr(&myfile);//disastrous!}

auto_ptr’s destructor calls delete to destroy myfile, although the latter was allocated on the stack. The result is undefined behavior. You can enforce this compile-time constraintby declaring the destructor as a private member:

class HeapOnly{private: ~HeapOnly();//auto and static objects are disabledpublic: //..};

How does this work? The compiler implicitly invokes the destructors of automatic and static objects when they go out of scope or when the program terminates, respectively. If the destructor isn’t public, you get a compilation error, which is exactly what you want:

HeapOnly h1;//compilation error:          //"Destructor for 'HeapOnly' is not accessible"int main{ HeapOnly h2; // ditto static HeapOnly h3; //ditto}

You can create such objects on the free-store. This raises yet another question: how do you destroy them? The solution is to delegate the destruction to another public member function:

class HeapOnly{private: ~HeapOnly();public: void destroy() {delete this;} //invoke the destructor};HeapOnly * p = new HeapOnly;//..use pp->destroy()

Admittedly, this technique isn’t perfect because you still can’t bind auto_ptr to such an object. This time the problem is that auto_ptr’s destructor can’t delete p. However, it shouldn’t be difficult to write an elementary smart pointer class whose destructor contains:


Disabling Allocation on the Free-store
It’s possible to define a class whose objects may be created on the stack or static memory but not on the free-store. For this purpose, override global new and deleteby declaring them as non-public class members:

class AutoStatic{private: void * operator new (size_t)                      {return 0;} //dummy implementation void operator delete (void*) {}public: //..};

The compiler will use the overridden versions of new and deleteto allocate and destroy objects of this class. Because these operators are inaccessible, any attempt to allocate such objects on the free-store would cause compilation errors:

int main(){ AutoStatic as; //fine static AutoStatic as2; //fine AutoStatic * p2= new AutoStatic; // error:    //'AutoStatic::operator new(unsigned int)'    //is not accessible  delete p2;//error:           //'AutoStatic::operator delete(void *)' is not                       //accessible.}

There is a loophole in this design, though. AutoStatic doesn’t override the array versions of new and delete. If you wish to disable dynamic allocation of AutoStaticarrays, override these operators as well:

class AutoStatic{private: //override global new[] and delete[] void * operator new [](size_t);  void operator delete [] (void*);//..};

Design Refinements
In cross-platform code, you should provide dummy definitions for the overriding new and deletebecause some implementations may call them implicitly from constructors and destructors.

Notice, also, that in a class hierarchy, a derived class uses the overridden new and deleteof its base class, unless it declares its own overriding versions of these operators.

A Walk Down Memory Lane
Seasoned programmers can find ways to bypass the constraints that I’ve shown here. For example, one could use placement new to construct objects on a buffer that was allocated from the free-store. However, a bullet-proof design isn’t the issue here. Rather, the aim is to protect your code from innocent human errors and to draw users’ attention to the memory-usage policy of a given class. In this respect, making a destructor non-public is sufficient for disabling static and automatic objects. Similarly, declaring new and deleteas private or protected class members is also an effective mechanism for disabling free-store allocation.

Share the Post:
XDR solutions

The Benefits of Using XDR Solutions

Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved

AI is revolutionizing fraud detection

How AI is Revolutionizing Fraud Detection

Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across

AI innovation

Companies Leading AI Innovation in 2023

Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several

data fivetran pricing

Fivetran Pricing Explained

One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of

kubernetes logging

Kubernetes Logging: What You Need to Know

Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes

ransomware cyber attack

Why Is Ransomware Such a Major Threat?

One of the most significant cyber threats faced by modern organizations is a ransomware attack. Ransomware attacks have grown in both sophistication and frequency over the past few years, forcing

data dictionary

Tools You Need to Make a Data Dictionary

Data dictionaries are crucial for organizations of all sizes that deal with large amounts of data. they are centralized repositories of all the data in organizations, including metadata such as