i had asked help on this question here Static member reclaiming memory and recovering from an exception
the program below is to allocate memory using own new operator. I have to throw exception on 5th object allocation and recover by freeing up memory (strange question i know, but it is assignment)
i have written the code here. allocation works, but when i try to call delete (through option '2') i get stuck in infinite loop.
#include <iostream>
#include <cstdlib>
using namespace std;
class object
{
int data;
static int count;
static void* allocatedObjects[5];
public:
object() { }
void* operator new(size_t);
void operator delete(void *);
void static release();
void static printCount()
{
cout << count << '\n';
}
~object()
{
release();
}
};
int object::count = 0;
void* object::allocatedObjects[5];
void* object::operator new(size_t size)
{
if (count > 5)
throw "Cannot allocate more than 5 objects!\n";
void *p = malloc(size);
allocatedObjects[count] = p;
count++;
return p;
}
void object::operator delete(void *p)
{
free(p);
count--;
}
void object::release()
{
while (count > 0)
{
delete static_cast<object*> (allocatedObjects[count]);
}
}
int main()
{
object *o[10];
int i = -1;
char c = 1;
while (c != '3')
{
cout << "Number of objects currently allocated : ";
object::printCount();
cout << "1. Allocate memory for object.\n";
cout << "2. Deallocate memory of last object.\n";
cout << "3. Exit.\n";
cin >> c;
if (c == '1')
{
try
{
i++;
o[i] = new object;
}
catch (char* e)
{
cout <<e;
object::release();
i = 0;
}
}
else if (c == '2' && i >= 0)
{
delete o[i];
i--;
}
}
return 0;
}
What am i doing wrong?
EDIT
I have fixed the delete problem. By getting rid of destructor. And explicitly calling release at end of main.
But now my catch block is not catching exception. After allocating 5 objects exception is thrown (as traced through debugger) but not caught. New Changes in the code do not affect the related code.
The infinite loop occurs because the destructor (~object()) is called before object::operator delete(). Your destructor is attempting to delete the most recent object allocated, which calls the destructor on the same object. The operator delete() is never being called.
I'm not sure what the allocatedObjects achieves here and the code will work without it. Get rid of the release () as well.
UPDATE
OK, so there's a need for the release (exception handling).
Don't call release from the destructor. Instead, make the operator delete() function set the allocatedObjects entry to 0, after the calling free (mirroring the operator new()). The release() function is only called during exception handling and makes sure un-freed memory is freed correctly (i.e. loop through allocatedObjects array and free non-zero entries and then setting them to zero.
Related
I created a queue data structure using a struct and a dynamically allocated array, I don't understand what is the right way to free or delete it without any memory leaks.
I have tried using the following:
delete[] q->data;
delete[] &(q->data);
delete &(q->data);
#include "queue.h"
void initQueue(queue* q, unsigned int size)
{
q->maxSize = size;
q->size = 0;
q->data = new unsigned int[size];
q->front = 0;
q->rear = 0;
}
void enqueue(queue* q, unsigned int newValue)
{
if (q->size != q->maxSize)
{
q->data[q->rear] = newValue;
q->size++;
q->rear++;
}
else
{
std::cout << "Queue is full! you can clean it and initialize a new one" << std::endl;
}
}
int dequeue(queue* q)
{
int i = 0;
if (q->size == 0)
{
std::cout << "Queue is empty!" << std::endl;
return EMPTY;
}
else
{
q->front++;
q->size--;
return q->data[q->front];
}
}
void cleanQueue(queue* q)
{
//the delete function
}
The technical right answer here is to delete q->data, as others have suggested. But...
right way to free or delete it without any memory leaks
The right way in C++, unless you're doing some exotic with allocation, is not to do your own memory management. Write a class that allocates in the constructor, and deletes in the destructor, as Chris suggested, is a great way to learn about RAII and how it saves you from the mental burden of manually writing "delete" everywhere.
But the right right way, if someone was paying me? I'd skip all that and use a vector.
#include <vector>
class MyQueue {
public:
MyQueue(unsigned int size) : data(size) { }
void enqueue(unsigned int value) { /* whatever... */ }
int dequeue() { /* whatever... */ }
private:
std::vector<unsigned int> data;
};
When this class goes out of scope or gets deleted, the vector will automatically be cleaned up. You don't even need to free or delete anything.
Symptoms
I was investigating using the chromium stack_container set specifically the StackString. I made a test program with the following:
#include <chromium/base/stack_container.h>
int main() {
StackString<300> s;
return 0;
}
This should create space on the stack and the string would reserve this space.
I was surprised to find, when i added some breakpoints to allocate in StackAllocator that the stack buffer is never returned to anyone. Ie, the general purpose allocater is always called:
pointer allocate(size_type n, void* hint = 0) {
if (source_ != NULL && !source_->used_stack_buffer_
&& n <= stack_capacity) {
source_->used_stack_buffer_ = true; // source_ is always NULL
return source_->stack_buffer(); // and so this is never returned.
} else {
return std::allocator<T>::allocate(n, hint); // This is always called.
}
}
Problem
After further investigation, i found that this is because when the std::basic_string type is created (as part of the construction of StackString) the VisualC++ implementation stores the allocater into some pair. Then when needing to use it, it copies it into a proxy:
void _Alloc_proxy()
{ // construct proxy
typename _Alty::template rebind<_Container_proxy>::other
_Alproxy(_Getal()); // Copies the allocator!
_Myproxy() = _Unfancy(_Alproxy.allocate(1)); // NOTE this for a later point.
...
The copy constructor of the StackAllocator will set the copies stack pointer to NULL. Hence the StackString could never work.
Furthermore, if the StackStringdidnt have this problem, it immediatly allocates space of 1, meaning after you add anything, it will quickly grow and suffer the same problem anyway.
Questions
Is this a bug, and if so by whom, VisualC++ or chromium?
If the first symptom doesn't occur, wouldn't the second item be a problem for most compilers anyway?
It seems that StackString was removed from the Chromium project: https://bugs.chromium.org/p/chromium/issues/detail?id=709273
But it's rather not a bug but some kind of optimization for a small string.
Visual Studio 2015/2017 will allocate a 16-byte std::_Container_proxy in the heap when compiling in "Debug" even for an empty string.
In "Release", we won't use the heap memory for the StackString.
I tested it with this code:
#include <iostream>
#include <new>
#include "stack_container.h"
std::size_t memory = 0;
std::size_t alloc = 0;
void* operator new(std::size_t s) throw(std::bad_alloc) {
// Put breakpoint here
memory += s;
++alloc;
return malloc(s);
}
void operator delete(void* p) throw() {
--alloc;
free(p);
}
void PrintMem_Info()
{
std::cout << "memory = " << memory << '\n';
std::cout << "alloc = " << alloc << '\n';
}
int main()
{
StackString<256> str;
PrintMem_Info();
str->append("Hello World!");
PrintMem_Info();
str[0] = '1';
str[1] = '2';
}
And my solution is:
pointer allocate(size_type n, void* hint = 0) {
#if defined(_MSC_VER)
if (n > stack_capacity)
{
n = stack_capacity;
}
#endif // if defined(_MSC_VER)
if (source_ != nullptr && !source_->used_stack_buffer_
&& n <= stack_capacity) {
source_->used_stack_buffer_ = true;
return source_->stack_buffer();
}
else {
return std::allocator<T>::allocate(n, hint);
}
}
I found this interesting exercise in Bruce Eckel's Thinking in C++, 2nd ed., Vol.1 in Chapter 13:
/*13. Modify NoMemory.cpp so that it contains an array of int
and so that it actually allocates memory instead of
throwing bad_alloc. In main( ), set up a while loop like
the one in NewHandler.cpp to run out of memory and
see what happens if your operator new does not test to
see if the memory is successfully allocated. Then add the
check to your operator new and throw bad_alloc*/
#include <iostream>
#include <cstdlib>
#include <new> // bad_alloc definition
using namespace std;
int count = 0;
class NoMemory {
int array[100000];
public:
void* operator new(size_t sz) throw(bad_alloc)
{
void* p = ::new char[sz];
if(!p)
{
throw bad_alloc(); // "Out of memory"
}
return p;
}
};
int main() {
try {
while(1) {
count++;
new NoMemory();
}
}
catch(bad_alloc)
{
cout << "memory exhausted after " << count << " allocations!" << endl;
cout << "Out of memory exception" << endl;
exit(1);
}
}
My question is: why does this code does not throw the bad_alloc, when ran completely out of memory (as per the Task Manager's resource monitor on Win7)?
I assume the global ::new char[sz] never returns with 0, even if the memory is full. But why? It even turns the Win7 OS into a numb, non-responding state once ran out of memory, still is does keep on trying to allocate new space.
(One interesting addition: I tryed it on Ubuntu too: the bad_alloc is not thrown either, still this OS does not goes frozen but this dangerous process gets killed before by the OS - smart isn't it?)
Your implementation of operator new is incorrect.
void* operator new(size_t sz) throw(bad_alloc)
{
void* p = ::new char[sz];
if(!p)
{
throw bad_alloc(); // "Out of memory"
}
return p;
}
::new already throws std::bad_alloc and you don't need to check return value of p pointer.
If you look g++'s libstdc++ source, they compare pointer to null after malloc, so you should do that too in order to simulate this:
_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
void *p;
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
while (__builtin_expect ((p = malloc (sz)) == 0, false))
{
new_handler handler = std::get_new_handler ();
if (! handler)
_GLIBCXX_THROW_OR_ABORT(bad_alloc());
handler ();
}
return p;
}
So it does not return 0 but throws an exception. The reason why don't you get it on linux I believe is that the process is always killed by the kernel (OOM-Killer) in such cases.
As #MarcGlisse pointed you may want to use nothrow (noexcept) version of new:
_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz, const std::nothrow_t&) GLIBCXX_USE_NOEXCEPT
{
void *p;
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
while (__builtin_expect ((p = malloc (sz)) == 0, false))
{
new_handler handler = std::get_new_handler ();
if (! handler)
return 0;
__try
{
handler ();
}
__catch(const bad_alloc&)
{
return 0;
}
}
return p;
}
As you see it will return 0 if allocation fails and it will catch all exceptions that can be raised by new_handler. Default new_handler throws std::bad_alloc.
But even in this case I think OOM-Killer will kill your application before you get something. If your question is more about why is it killed? then I recommend you to read about OOM killer policy.
I've found my error: I called new wrong: new NoMemory();
The correct way to do is new NoMemory; (without the parentheses)
Now it works like a charm, like this:
#include <iostream>
#include <cstdlib>
#include <new> // bad_alloc definition
using namespace std;
int count = 0;
class NoMemory {
int array[100000];
public:
void* operator new(size_t sz) throw(bad_alloc)
{
void* p = ::new(std::nothrow) char[sz];
if(0 != p)
return p;
throw bad_alloc();
}
};
int main() {
try {
while(1) {
count++;
new NoMemory;
}
}
catch(bad_alloc)
{
cout << "memory exhausted after " << count << " allocations!" << endl;
cout << "Out of memory exception" << endl;
exit(1);
}
}
Kindly help me figure out where the issue is. I have followed the rule of three as well and made several modifications to the code.
#include <iostream>
using namespace std;
class AStack {
public:
AStack();
AStack(int);
AStack(const AStack&);
~AStack();
AStack& operator = (const AStack& s);
void push(int);
int pop();
int top();
bool isEmpty();
void flush();
private:
int capacity ;
int* a;
int index = -1; // Index of the top most element
};
AStack::AStack() {
a = new int[25];
capacity = 25;
}
AStack::AStack(int size) {
a = new int[size];
capacity = size;
}
AStack::AStack(const AStack& s) {
capacity = s.capacity;
delete[] a; // To avoid memory leak
a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
}
AStack::~AStack() {
delete[] a;
}
AStack& AStack::operator = (const AStack& s) {
capacity = s.capacity;
delete[] a; // To avoid memory leak
int* a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
return *this;
}
void AStack::push(int x) {
if (index == capacity - 1) {
cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
return;
}
a[++index] = x;
}
int AStack::pop() {
if (index == -1) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
return a[index--];
}
int AStack::top() {
if (index == -1) {
cout << "\n\nNo elements in the Stack\n\n";
return -1;
}
return a[index];
}
bool AStack::isEmpty() {
return (index == -1);
}
void AStack::flush() {
if (index == -1) {
cout << "\n\nNo elements in the Stack to flush\n\n";
return;
}
cout << "\n\nFlushing the Stack: ";
while (index != -1) {
cout << a[index--] << " ";
}
cout << endl << endl;
}
AStack& reverseStack(AStack& s1) {
AStack s2;
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1 = s2;
return s1;
}
int main() {
AStack s1;
s1.push(1);
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
s1 = reverseStack(s1);
cout << "\n\nFlushing s1:\n";
s1.flush();
system("pause");
return 0;
}
I fail to understand how even after defining the appropriate copy assignment operator, the values in s1 after returning from the function are garbage values.
If your copy constructor is correct, and your destructor is correct, your assignment operator could be written in a much easier and safer fashion.
Currently, your assignment operator has two major flaws:
No check for self-assignment.
Changing the state of this before you know you can successfully allocate the
memory (your code is not exception safe).
The reason for your error is that the call to reverseStack returns a reference to the current object. This invoked the assignment operator, thus your assignment operator was assigning the current object to the current object. Thus issue 1 above gets triggered.
You delete yourself, and then you reallocate yourself, but where did you get the values from in the loop to assign? They were deleted, thus they're garbage.
For item 2 above, these lines change this before you allocate memory:
capacity = s.capacity;
delete[] a; // To avoid memory leak
What happens if the call to new[] throws an exception? You've messed up your object by not only changing the capacity value, but you've also destroyed your data in the object by calling delete[] prematurely.
The other issue (which needs to be fixed to use the copy/swap idiom later in the answer), is that your copy constructor is deallocating memory it never allocated:
AStack::AStack(const AStack& s) {
capacity = s.capacity;
delete[] a; // ?? What
Remove the line with the delete[] a, since you are more than likely calling delete[] on a pointer that's pointing to garbage.
Now, to rid you of these issues with the assignment operator, the copy/swap idiom should be used. This requires a working copy constructor and a working destructor before you can utilize this method. That's why we needed to fix your copy constructor first before proceeding.
#include <algorithm>
//...
AStack& AStack::operator = (AStack s)
{
std::swap(capacity, s.capacity);
std::swap(a, s.a);
std::swap(index, s.index);
return *this;
}
Note that we do not need to check for self assignment, as the object that is passed by value is a brand new, temporary object that we are taking the values from, and never the current object's values (again, this is the reason for your original code to fail).
Also, if new[] threw an exception, it would have been thrown on the call to the assignment operator when creating the temporary object that is passed by value. Thus we never get the chance to inadvertently mess up our object because of new[] throwing an exception.
Please read up on what the copy/swap idiom is, and why this is the easiest, safest, and robust way to write an assignment operator. This answer explains in detail what you need to know:
What is the copy-and-swap idiom?
Here is a live example of the fixed code. Note that there are other changes, such as removing the default constructor and making the Attack(int) destructor take a default parameter of 25.
Live Example: http://ideone.com/KbA20D
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I was told that putting all pointers in the catch block is bad OO programming. Cleanup occurs in the catch block. How does it violate every rule of OO design?
Here is a sample code:
#include <iostream>
#include <string>
using namespace std;
class Error
{
friend int main();
public:
Error(int* p, string m) : arr(p), msg(m) { }
private:
int* arr;
string msg;
};
void initialize();
int main()
{
try {
initialize();
}
catch(Error& err) {
cout<<endl<< "Error! "<< err.msg <<endl<<endl;
delete [] err.arr;
}
return 0;
}
void initialize()
{
int size;
cout<<"Enter the number of elements: ";
cin >> size;
int* myArray = new int[size];
cout<<"Enter the elements: " <<endl;
for (int i=0; i<size; ++i)
cin >> myArray[i];
if (!cin.good())
throw Error(myArray, (string)"bad input!");
cout<<endl<<"You entered:"<<endl;
for (int i=0; i<size; ++i)
cout << myArray[i] << " ";
cout<<endl;
delete [] myArray;
}
Please ignore this line. I'm just trying to get this question posted.
To deal with resources, C used to focus on managing the execution paths. the programmer had to make sure that for every possible path, the resources were freed.
So it was normal to end with code like that :
Notice that most of the code is there to handle error(s).
HRESULT
CreateNotifyIcon(NotifyIcon** ppResult)
{
NotifyIcon* icon = 0;
Icon* inner = 0;
const wchar_t * tmp1 = 0;
HRESULT hr = S_OK;
if ( SUCCEEDED(hr) ) {
icon = new (nothrow) NotifyIcon();
if ( !icon ) hr = E_OUTOFMEM;
}
if ( SUCCEEDED(hr) )
hr = icon->set_text("Blah blah blah");
if ( SUCCEEDED(hr) ) {
inner = new (nothrow) Icon(...);
if ( !inner )
hr = E_OUTOFMEM;
else {
Info info;
hr = GetInfo( &info );
if ( SUCCEEDED(hr) )
hr = icon->set_icon(inner, info);
if ( SUCCEEDED(hr) )
inner = NULL;
}
}
if ( SUCCEEDED(hr) )
hr = icon->set_visible(true);
if ( SUCCEEDED(hr) ) {
*ppResult = icon;
icon = NULL;
} else {
*ppResult = NULL;
}
cleanup:
if ( inner ) delete inner;
if ( icon ) delete icon;
return hr;
}
In C++, this is not the right way because you have exceptions. For instance :
String EvaluateSalaryAndReturnName( Employee e )
{
if( e.Title() == "CEO" || e.Salary() > 100000 )
{
cout << e.First() << " " << e.Last()
<< " is overpaid" << endl;
}
return e.First() + " " + e.Last();
}
There are 23 different execution paths in that snippet of code.
So C++ chose to focus on the resources instead. Each function (should) handle a limited number of resources. Roughly speaking, you put a watchdog on each resource to make sure they are properly released/freed. This watch dog is RAII. Indeed, whatever the execution path may be, you are 100% sure the destructor of all objects allocated on the stack will be called. That way, by putting your resources into RAII object (STL containers, std::unique_ptr,...), you can deal with exceptions without any problem of leaked resource.
Look at the difference :
BAD WAY
void function(int n){
int* p = 0;
int* c = 0;
try{
p = new int[n];
c = new int[n*2];
}
catch(std::exception const& e){
delete[] c;
delete[] p;
throw;
}
delete[] c;
delete[] p;
}
int main(){
try{
function(1000);
} catch (std::exception const& e){
std::cerr<<e.what()<<std::endl;
}
}
GOOD WAY
void function(int n){
std::unique_ptr<int[]> p(new int[n]); //or std::vector
std::unique_ptr<int[]> c(new int[n*2]);
}
int main(){
try{
function(1000);
} catch (std::exception const& e){
std::cerr<<e.what()<<std::endl;
}
}
The problem is, that you have to delete the array in all possible ways to leave the function. This may be easy if you have only one or two ways, but gets confusing with more. Even in your code you have one delete already outside the function, what it makes hard to find.
Use smart pointers to target that issue. They deallocate their content when they get out of scope. That way you don't have to bother for the destruction of the array. As soon as the function is done, the array will be destroyed.
Here is some documentation for smart pointers:
unique_ptr
shared_ptr
The C++ Standard n3337 § 15.2/3 says:
The process of calling destructors for automatic objects constructed
on the path from a try block to a throw-expression is called “stack
unwinding. (...)”
The problem with your code is that pointer to array is allocated inside try block, so it is no longer alive when control reaches catch block. You cannot do
To correct this you should declare a pointer before try block:
int* myArray;
try{
function(1000); // allocate an array and point myArray to it
} catch (std::exception const& e){
delete [] myArray; // OK, myArray pointer is valid here
}
This will delete the objects and return memory to the system. Such approach is taken for example in std::uninitialized_fill. But you got the better possibility. To free yourself from the burden of deallocating memory you can consider using smart pointer or a handle to an array (a class that wraps around a resource): representing each resource as a class is the foundation of approach called RAII.
try{
MyArray myArray(1000); // allocate an array in constructor
} catch (std::exception const& e){
// destructor for myArray has deleted ints & returned memory already
}