SCIP provides three ways for allocating memory:
Whenever possible, the first two should be used, because of reasons detailed below.
In the following, we provide a brief description of these methods. We refer the reader to the dissertation of Tobias Achterberg for more details. We also present best practice models.
The main goals for providing such particular methods are:
Debugging: All of the possibilities provide methods to detect memory leaks. Together with tools like valgrind, this can be quite effective in avoiding such problems.
SCIP offers its own block memory handling, which allows efficient handling of smaller blocks of memory in cases in which many blocks of the same (small) size appear. This is adequate for branch-and-cut codes in which small blocks of the same size are allocated and freed very often (for data structures used to store rows or branch-and-bound nodes). Actually, most blocks allocated within SCIP have small sizes like 8, 16, 30, 32, 64. The idea is simple: There is a separate list of memory blocks for each interesting small size. When allocating memory, the list is checked for a free spot in the list; if no such spot exists, the list is enlarged. Freeing just sets the block to be available. Very large blocks are handled separately. See the dissertation of Tobias Achterberg for more details.
One important comment is that freeing block memory requires the size of the block in order to find the right list.
The most important functions are
An example code is:
In addition to block memory, SCIP offers buffer memory. This should be used if memory is locally used within a function and freed within the same function. For this purpose, SCIP has a list of memory buffers that are reused for this purpose. In this way, a very efficient allocation/freeing is possible.
Note that the buffers are organized in a stack, i.e., freeing buffers in reverse order of allocation is faster.
The most important functions are
SCIP 3.2 introduced a new type of buffer memory, the clean buffer. It provides memory which is initialized to zero and requires the user to reset the memory to zero before freeing it. This can be used at performance-critical places where only few nonzeros are added to a dense array and removing these nonzeros individually is much faster than clearing the whole array. Similar to the normal buffer array, the clean buffer should be used for temporary memory allocated and freed within the same function.
The most important functions are
SCIP provides an access to the standard C functions malloc
and free
with the additional feature of tracking memory in debug mode. In this way, memory leaks can be easily detected. This feature is automatically activated in debug mode.
The most important functions are
Since allocating and freeing memory is very crucial for the speed and memory consumption of a program, it is important to keep the following notes and recommendations in mind.
The following holds for all three types of memory functions:
size_t
, such that negative sizes are converted into very large values.NOBLKMEM=true
, NOBUFMEM=true
, NOBLKBUFMEM=true
that turn off the usage of block memory, buffer memory, as well as block and buffer memory, respectively. Since, the internal block and buffer memory is freed at the end (leaving no memory leaks), turning them off allows tools like valgrind to find memory leaks.CHECKMEM
in memory.c.