Question

Do you know if there is a way to bring back malloc in its initial state, as if the program was just starting ?

reason : I am developing an embedded application with the nintendods devkitpro and I would like to be able to improve debugging support in case of software faults. I can already catch most errors and e.g. return to the console menu, but this fails to work when catching std::bad_alloc.

I suspect that the code I use for "soft reboot" involves malloc() itself at some point I cannot control, so I'd like to "forget everything about the running app and get a fresh start".

Was it helpful?

Solution

The only way to get a fresh start is to reload the application from storage. The DS loads everything into RAM which means that the data section is modified in place.

OTHER TIPS

There is no way of doing this portably, though concievably an embedded implementation of C++ might supply it as an extension. You should instead look at writing your own allocation system, using memory pools, or use an existing library.

Only time I did something similar, we used our own allocator which would keep a reference to each allocated blocks. If we wanted to rollback, we would free all the allocated blocks and do a longjmp to restart the programme.

Squirrel away a bit of memory in a global location e.g.

int* not_used = new i[1024];

Then when you get a std::bad_alloc, delete not_used and move on to your error console. The idea is to give your crash handler just enough space to do what you need. You'll have to tune how much memory is reserved so that your console doesn't also received out of memory errors.

If you're clever, not_used could actually be used. But you'd have to be careful that whatever was using memory could be deleted without notice.

I suppose if nothing else is running you could zero-write the whole memory block that the API provides on the Nintendo? But otherwise just keep track of your allocates.

In fact, if you create a CatchAndRelease class to keep a reference to each and every allocated memory block, at the required time you could go back and clear those out.

Otherwise, you may need to write your own memory pool, as mentioned by Neil.

Do you ever need to free memory in anything other than last-in-first-out order? If not, I'd suggest that you define an array to use all available memory (you'll probably have to tweak the linker files to do this) and then initialize a pointer to the start of that array. Then write your own malloc() function:

char *allocation_ptr = big_array;

void *malloc(size_t n)
{
  void *temp = (void*)allocation_ptr;
  if (allocation_ptr > END_OF_ALLOCATION_AREA - n)
    return 0;
  allocation_ptr += n;
  return temp;
}

void free_all_after(void *ptr)
{
  if (ptr)
    allocation_ptr = (char*)ptr;
}

In this implementation, free_all_after() will free the indicated pointer and everything allocated after it. Note that unlike other implementations of malloc(), this one has zero overhead. The LIFO allocation is very limiting, but for many embedded systems it would be entirely adequate.

std::bad_alloc occurs when new fails and cannot allocate the memory requested. This will normally occur when the heap has run out of memory and therefore cannot honour the request. For this reason, you will not be able to allocate any new memory reliably in the cleanup.

This means that you may not allocate new memory for cleanup. Your only hope of cleaning up successfully is to ensure that memory for the cleanup code is pre-allocated well before you actually need it.

Objects can still be newed into this cleanup memory using the inplace new operator (ie new where you supply a memory address)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top