user4592253
user4592253

Reputation:

realloc: Program received signal SIGTRAP, Trace/breakpoint trap

I am working on a program that stores an arbitrarily long list of contacts (names and phone numbers). The entries are stored in an array that is resized each time a new element is added with the realloc function. The first contact can be added and displayed normally. However, when I try to add the second contact, the program crashes with the following message:

Program received signal SIGTRAP, Trace/breakpoint trap.
In ntdll!RtlZeroHeap () (C:\WINDOWS\SYSTEM32\ntdll.dll)

No breakpoints have been set in my editor. The debugger says the problem is on the line containing the realloc statement. How can I fix this issue? I have included the relevant sections of code below.

#define STRING_LENGTH 32

typedef struct entry_t {
    char name[STRING_LENGTH];
    char number[STRING_LENGTH];
} Entry;

void *add_entry(Entry*, int);

int main()
{
    int entry_count = 0;
    Entry *entries = calloc(1, sizeof(Entry));
    int choice = 0;

    while (1) {
        printf("Options:\n1) Add Entry\n2) Modify Entry\n3) Print Entries\n4) Exit\n\nSelect an option: ");
        scanf(" %d", &choice);
        switch (choice) {
        case 1:
            entries = add_entry(entries, entry_count++);
            break;
            // ...
        }
    }
}

void *add_entry(Entry *entries, int current_count)
{
    Entry entry;

    printf("Enter name: ");
    scanf(" %[^\n]s", entry.name);
    printf("Enter number: ");
    scanf(" %[^\n]s", entry.number);
    printf("\n");

    entries[current_count] = entry;
    return realloc(entries, sizeof(Entry) * (current_count + 1));
}

Upvotes: 0

Views: 4598

Answers (1)

Pablo
Pablo

Reputation: 13590

There is a logic problem here. You initially allocate space for one object with calloc then call add_entry with the count equals to 0.

Then you add the new entry at index current_count which is 0 at this point. Then you resize the memory with current_count + 1, which is also 1. So you are not resizing the memory at all.

In the next iteration, entry_count is 1 and you add a new element at entries[1]. And that's the problem, you are accessing the memory out of bounds, because you still have space for only one object at this time.

Instead of reallocating by current_count + 1, you should reallocate by current_count + 2, so that the next iteration has space to put the new elements at the end of the memory.

void *add_entry(Entry *entries, int current_count)
{
    Entry entry;

    printf("Enter name: ");
    scanf(" %[^\n]s", entry.name);
    printf("Enter number: ");
    scanf(" %[^\n]s", entry.number);
    printf("\n");

    entries[current_count] = entry;
    return realloc(entries, sizeof(Entry) * (current_count + 2));  // <-- +2
}

Note that your current_count variable is always one step behind the real size of the allocation, that's why you need the +2

edit

Note also that the more natural way would be to resize first, and then insert the new object. So I would initialize the memory with NULL and do it like this:

int main()
{
    size_t entry_count = 0;
    Entry *entries = NULL, *tmp;
    int choice = 0;

    while (1) {
        printf("Options:\n1) Add Entry\n2) Modify Entry\n3) Print Entries\n4) Exit\n\nSelect an option: ");
        scanf(" %d", &choice);
        switch (choice) {
        case 1:
            tmp = add_entry(entries, &entry_count);
            if(tmp == NULL)
            {
                // error handling
                // entries still point to the old memory
                // could be useful in error handling

                free(entries);
                return 1;
            }

            entries = tmp;
            break;
            // ...
        }
    }
}

void *add_entry(Entry *entries, size_t *current_count)
{
    if(current_count == NULL)
        return NULL;

    Entry entry;

    printf("Enter name: ");
    scanf(" %[^\n]s", entry.name);
    printf("Enter number: ");
    scanf(" %[^\n]s", entry.number);
    printf("\n");

    if(entries == NULL)
        *current_count = 0;

    Entry *tmp = realloc(entries, (*current_count + 1) * sizeof *entries);

    if(tmp == NULL)
        return NULL;

    entries = tmp;

    entries[(*current_count)++] = entry;

    return entries;
}

Note here that the realloc and the increment of the counting variable happens in the same function. Only when everything goes OK, you should increase the counter. Also note that entries is initialized with NULL, because realloc(NULL, size) is equivalent to malloc(size).

Upvotes: 1

Related Questions