3

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".

Mark Mayo
  • 12,230
  • 12
  • 54
  • 85
PypeBros
  • 2,607
  • 24
  • 37
  • btw, the malloc implementation i'm using has malloc_stats and mallinfo, but not malloc_set_state nor malloc_get_state which might (?) have offered a solution. – PypeBros Dec 16 '09 at 16:25
  • looks like my devkit is using "newlib"'s mallocator. I'm gonna study this to figure out a better way to investigate the problem. – PypeBros Dec 18 '09 at 16:54

7 Answers7

3

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.

2

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.

2

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.

deft_code
  • 57,255
  • 29
  • 141
  • 224
  • Nice idea. It will require a bit of tweaking because i ignore where and how much memory is needed, but if i manage to find out, it could do the trick. I'm not too sure that *lack* of memory is the root of the problem, though. I'm afraid some buffer overflow could also have trashed malloc's internal state. – PypeBros Dec 16 '09 at 16:11
1

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.

Mark Mayo
  • 12,230
  • 12
  • 54
  • 85
1

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.

WinterMute
  • 336
  • 3
  • 5
  • ... which in turn stresses out the fact that loading an app in RAM from storage should never use malloc() ... – PypeBros Aug 28 '12 at 08:42
1

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.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • yes, unfortunately I cannot simplify memory allocation to that point. – PypeBros Dec 22 '10 at 10:05
  • 1
    @sylvainulg: That memory-management approach is suitable for some jobs, but not all. A slight variation is to have a block of memory which is allocated both from the top and the bottom (in which case one can do LIFO releases from the top and bottom independently). A third variation (used in 1980's-era microcomputer BASIC interpreters) if it's easy to find all pointers to memory (using double-indirected pointers could help with this) is to use garbage compaction instead of a free list. This approach has limitations, but avoids fragmentation. – supercat Dec 22 '10 at 15:58
0

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)

doron
  • 27,972
  • 12
  • 65
  • 103