Controlling librcheck through API calls

In your application code, you can use the mallopt() function to control memory checking and tracing. Calls to mallopt() modify the parameters and behavior of librcheck.

Adapting your code to use this librcheck API (and rebuilding and relaunching the application) is admittedly more work than configuring Memory Analysis in the IDE or sending signals or commands to a target process. However, using the API lets you perform leak checks and output heap statistics at specific places in the code.

For information about all commands for controlling memory data collection, see the mallopt() entry in the C Library Reference. Here, we demonstrate how to use some common commands.

Sample program

Your program must include the debug version of the allocation library (rcheck/malloc.h); otherwise, the usage of any debug commands will cause a build error.

Consider the following program:
#include <stdlib.h>
#include <string.h>
#include <rcheck/malloc.h>
#include <sys/neutrino.h>

void foo1() {
    char* p = malloc(40); // malloc that's irrelevant for tracing
    struct _msg_info msg_rcvd;

    // Suppose we copy in data that's too large for the memory area;
    // in this case, we read in a structure that's 48 bytes into our
    // area of 40 bytes
    memcpy(p, &msg_rcvd, sizeof(struct _msg_info));

    free(p);
}

char* foo2() {
    char* p = malloc(20); // malloc that's relevant for tracing

    // Suppose we do other work in here to store data in the memory
    // area referred to by "p"; then, we return the pointer
    return p;
}

int main() {
    // If we suspect that the first function has problems with writing
    // out of bounds, we enable boundary checking
    mallopt(MALLOC_CKACCESS,1);

    foo1();

    // After the function returns, we disable boundary checking
    mallopt(MALLOC_CKACCESS,0);

    // To track the memory allocated by the next function, we turn
    // memory tracing on
    mallopt(MALLOC_TRACING,1);

    // We don't store the pointer returned by this function, meaning
    // we can't use the referenced data and hence, we create a leak
    foo2();

    // After the function returns, we turn memory tracing off
    mallopt(MALLOC_TRACING,0);

    // Just before exiting, we report all outstanding memory leaks
    mallopt(MALLOC_DUMP_LEAKS,1);

    return 0;
}
Based on the tracing commands, you'll see one allocation event for foo2() but no allocation or deallocation events for foo1(). You'll also see these memory errors:
  • a data write to an improper heap area (for the memcpy() operation in foo1())
  • a memory leak of 20 bytes (for the memory allocated in foo2() but not freed)