C programming question
Posted: Sat Jan 18, 2014 2:35 am
I have a board structure that looks like:
'some stuff' basically contains everything that is going to be recomputed dynamically upon playing and undoing moves. In contrast, some information either cannot be recomputed on undo, or it would be a waste of performance to do so. This information is what I put in 'struct undo_info'.
The triplet (begin, end, ui) represent an undo stack: it's a dynamic array that starts at 'begin', ends at 'end' (not included) and whose current position (ie. stack top) is 'ui'.
C is a Spartan language, in which the programmer needs to take care of memory allocation, reallocation, and freeing himself. What is the standard strategy to deal with such problems? Here's the simplest strategy I can think of:
1/ when I call clear_board(), I allocate (let's say) 16 elements:
2/ when I call play(), to play a move on the board, I need to start by adding a new element undo_info on top of the stack, copy the current one's content into it. Of course, this can lead to ui >= end, in which case, I need to call realloc(), to grow the stack by another 16 elements:
The problem with that strategy is that the burden of freeing memory now belongs to the foreign code. And in rather subtile ways. Example of such foreign code that could leak:
Now play/undo some moves (what a typical search would do). note that the undo_info buffer will grow but never shrink. This is a good thing (lazy reallocation).
Calling set_pos() again will call clear_bord(), which will inevitably leak. The point is that clear_board() cannot start by freeing the buffer, because it cannot know if the pointer contains garbage or a valid adress that needs to be freed. Also, a more economical strategy would be to not free but reuse the already allocated buffer.
In this scheme, the correct solution would be to free the buffer in the foreign code, before the second call to set_pos(), which is ugly because the foreign code should not have to know about such ugly details.
What strategy would you recommend ?
PS: Please don't lecture me about the benefits of C++ and STL/Boost etc. This is a C question.
Code: Select all
struct board {
// some stuff
struct undo_info *begin, *end, *ui;
};
The triplet (begin, end, ui) represent an undo stack: it's a dynamic array that starts at 'begin', ends at 'end' (not included) and whose current position (ie. stack top) is 'ui'.
C is a Spartan language, in which the programmer needs to take care of memory allocation, reallocation, and freeing himself. What is the standard strategy to deal with such problems? Here's the simplest strategy I can think of:
1/ when I call clear_board(), I allocate (let's say) 16 elements:
Code: Select all
begin = calloc(sizeof(undo_info), 16);
Code: Select all
if (ui+1 >= end)
begin = realloc(begin, sizeof(undo_info) * (end - begin + 16));
Code: Select all
struct board b;
set_pos(&b, "2r1qn2/2P2pk1/2RQ2p1/4P2p/1R5P/P7/7P/K7 w - - 5 64 ");
Calling set_pos() again will call clear_bord(), which will inevitably leak. The point is that clear_board() cannot start by freeing the buffer, because it cannot know if the pointer contains garbage or a valid adress that needs to be freed. Also, a more economical strategy would be to not free but reuse the already allocated buffer.
Code: Select all
// Memory leak!
set_pos(&b, "2r1qn2/2P2pk1/2RQ2p1/4P2p/1R5P/P7/7P/K7 w - - 5 64 ");
What strategy would you recommend ?
PS: Please don't lecture me about the benefits of C++ and STL/Boost etc. This is a C question.