cmemory-managementmemory-leaksconstexpr

constexpr in relation to memory leaks in C


I am learning C and today I wrote some code to turn roman numerals to numbers.

In my program I have a const int MAXWORTLEN = 16; inside of int main(), as well as an array of booleans, which I have declared with: bool *vorzeichen = calloc(MAXWORTLEN, sizeof(bool));, which I free() in the end.

I am programming in CLion which sometimes gives little tips to "improve" the program like making an int into a const int if it fits the case. It also warns against memory leaks, unreachable code, etc.

By keeping my MAXWORTLEN a const int, CLion warns that "Allocated memory is leaked". By changing to constexpr int MAXWORTLEN = 16;, as it suggests, the warning goes away.

All warnings that Clion gives are:

Function 'main' always returns 0 :22
Allocated memory is leaked :29
Leak of memory allocated in function 'main' :33
Variable 'MAXWORTLEN' can be made constexpr :23

The file is a .c file. I am using build tool ninja and gcc as a C compiler.

#include <stdio.h>
#include <stdlib.h>

int rom_wert(char c) {

    if(c>='a' && c<='z') {
        c = c + ('A' - 'a');
    }
    switch (c) {
        case 'I': return 1;
        case 'V': return 5;
        case 'X': return 10;
        case 'L': return 50;
        case 'C': return 100;
        case 'D': return 500;
        case 'M': return 1000;

        default: return -1;
    }
}

int main() {
    constexpr int MAXWORTLEN = 16;
    printf("Eingabe: ");

    char *eingabe = calloc(MAXWORTLEN, sizeof(char));
    scanf("%15s", eingabe);

    bool *vorzeichen = calloc(MAXWORTLEN, sizeof(bool));

    for(int i=0; eingabe[i] != '\0'; i++) {
        if(rom_wert(eingabe[i]) == -1) {
            return 0;
        }
        if(rom_wert(eingabe[i]) < rom_wert(eingabe[i+1])) {
            vorzeichen[i] = true;
        }
    }

    int summe = 0;
    for(int j=0; eingabe[j] != '\0'; j++) {
        if(vorzeichen[j] == 1)
            summe = summe - rom_wert(eingabe[j]);
        else if(vorzeichen[j] == 0)
            summe = summe + rom_wert(eingabe[j]);
    }

    printf("Ausgabe: %d", summe);

    free(eingabe);
    free(vorzeichen);

    return 0;
}                                           

Where is the memory leak in the original code, and how does constexpr resolve it? Any answer is greatly appreciated, as my only goal in this exercise is to learn :)


Solution

  • Where is the memory leak in the original code

    The memory leak occurs when the return 0 line is executed in the for-loop near the top of main. The return 0 means that the rest of the function is never executed and therefore the calls to free() are never made. (On a modern OS with resource-tracking, that doesn't much matter since the program then exits and all of its memory is automatically freed anyway, but it is still technically a leak)

    and how does constexpr resolve it?

    I don't think it does, but my suspicion is that tagging the variable with constexpr may have allowed the compiler/optimizer to implicitly remove the calloc() and free() calls entirely and replace them with one or more stack-based arrays instead, in which case there would be no memory leak as there was never any heap allocation to begin with.