cmemory-managementfree

Why is free() causing an error here without the else block?


This is the full code I have right now. I have tried everything that I could think of, but when I have the contents of the else block, despite the code skipping through it, the code runs smoothly with no memory leaks.

The code doesn't pass through the else block, so it's useless to what I can see, but if I empty or remove the else block, the __debugbreak triggers on free inside DeleteSedex.

What causes this to happen?

sedex.h:

#ifndef KAAL_SEDEX_H
#define KAAL_SEDEX_H
#include "limits.h"
#ifdef ULLONG_MAX
#include "assert.h"
#include "crtdbg.h"
#include "stdio.h"
#include "stdlib.h"
#define MEMORY_UNINITIALIZED (size_t)(0xCCCCCCCCCCCCCCCC)
#define MEMORY_AVAILABLE(ptr) (assert(NULL != ptr && MEMORY_UNINITIALIZED != (size_t)(ptr)))

typedef char* string;
typedef long long llong;
typedef enum { true, false } bool;

typedef struct sedecimstruct {
    size_t length;
    llong* content;
} *sedex;

sedex CreateSedex(string source);
void DeleteSedex(sedex target);
#endif
#endif

sedex.c:

#include "sedex.h"

int main(void)
{
    sedex n = CreateSedex("+");
    DeleteSedex(n);
    _CrtDumpMemoryLeaks();
    return 0;
}

sedex CreateSedex(string source)
{
    struct sedecimstruct output;
    bool sgned = source[0] == '+' || source[0] == '-';
    if (source == NULL || strlen(source) == 0 ||
        strlen(source) == 1 && sgned)
    {
        output.length = 2;
        output.content = calloc(output.length, sizeof(llong));
    }
    else
    {
        size_t digits = strlen(source) - sgned,
            mod = digits & 0xf;
        bool excess = mod > 0;
        output.length = (digits >> 4) + excess + 1;
        output.content = malloc(output.length * sizeof(llong));
        output.content[0] = source[0] == '-';
        char sedecim[17] = { 0 };
        MEMORY_AVAILABLE(output.content);
        for (size_t i = 1; i <= digits; i++)
        {
            sedecim[(i - 1) & 0xf] = source[i - 1 + sgned];
            if ((i & 0xf) == 0)
            {
                output.content[i >> 4] = atoll(sedecim);
                memset(sedecim, 0, sizeof(sedecim));
                continue;
            }
            if (i == digits && excess)
            {
                output.content[output.length - 1] = atoll(sedecim);
                memset(sedecim, 0, sizeof(sedecim));
            }
        }
    }
    return &output;
}

void DeleteSedex(sedex target)
{
    free(target->content); // breakpoint triggers here when else is empty or removed
    target->content = target->length = NULL;
}

Solution

  • Okay, I get it now. I cannot return &output. I must allocate a pointer with malloc first, and return that.

    // struct sedecimstruct output;
    sedex output = malloc(sizeof(struct sedecimstruct));
    // ... do something to the output ...
    return output;