1
votes

I have some code lines which are part of the bigger project. My code compiled with gcc (Debian 4.7.2-5) shows some invalid free/delete error while being analyzed with valgrind. However, when I compile it with gcc (Ubuntu/Linaro 4.8.1) the error is gone.

Here's the error message:

==4505== Invalid free() / delete / delete[] / realloc()
==4505==    at 0x4C27D4E: free (vg_replace_malloc.c:427)
==4505==    by 0x401195: method (test.c:202)
==4505==    by 0x401429: main (test.c:264)
==4505==  Address 0x401600 is not stack'd, malloc'd or (recently) free'd
==4505== 
Linux ==4505== 
==4505== HEAP SUMMARY:
==4505==     in use at exit: 0 bytes in 0 blocks
==4505==   total heap usage: 1,394 allocs, 1,395 frees, 95,379 bytes allocated
==4505== 
==4505== All heap blocks were freed -- no leaks are possible
==4505== 
==4505== For counts of detected and suppressed errors, rerun with: -v
==4505== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)

And here's the piece of code that fails:

for (i = 0; etcFilenames[i] != NULL; i++)
{
    for (j = 0; j < OS_NUM; j++)
    {
        if (!strcmp(etcFilenames[i], releaseFilenames[j]))
        {
            filename = (char *)releaseFilenames[j];
            char *tmp = readEtcFile(filename);

            if (strlen(tmp) == 0)
            {
                free(tmp);
                continue;
            }
            else
            {
                name = malloc(sizeof(char) * (strlen(tmp) + 1));
                strcpy(name, tmp);
                free(tmp);
                break;
            }
        }
    }
}

if (uname(&sysInfo) != -1)
{
    len = sizeof(sysInfo.sysname) + strlen(name) + 1;
    os->sysname  = malloc(sizeof(char) * len);
    memset (os->sysname, 0, len);
    strcpy(sysname, sysInfo.sysname);
    strcat(sysname, " ");
    strcat(sysname, name);

    version  = malloc(sizeof(char) * (sizeof(sysInfo.release) + 1));
    memset (version, 0, sizeof(sysInfo.release));
    strcpy(version, sysInfo.release);

    free(name);
}

Valgrind complains about this last line: free(name); when all used variables are declared as follows:

struct utsname sysInfo;
FILE *osArch, *distribName;
char *arch, *name = "";
char buff[1024];
int len = 0;
char **etcFilenames = getEtcFilenames();
unsigned int i = 0, j = 0;

const char *releaseFilenames[OS_NUM];
char *filename = "";

My main concern is that I do not know if it is my faul the error came up, or its the gcc issue? How can I know what version is fine? (When I comment out free(name); on (Debian 4.7.2-5) gcc its then ok but then gcc 4.8.1 complains about the memory leaks ...)

1
Where is name declared, and are you sure it's allocated when you free it?Happington
@Happington: Oh, thanks, now I see, stupid me. It should be char *arch, *name = NULL; Thanks! :) Anyway, when I changed this, I have another issue: pastie.org/private/4esf3ojyidtdfhc34w5zw which refers to the line: len = sizeof(sysInfo.sysname) + strlen(name) + 1;mirx
Look at the address. 0x00 (NULL.) While this call is legal on SOME systems, (*nix core tends to allow this call, but give strange results) and illegal on others (NT) Valgrind will quickly see that this is very much NOT what you want to do, and throw an error. The root of the error comes from the fact you're calling strlen() on a NULL pointer. Make sure you actually malloc() name before calling strlen() on it.Happington
strlen on a NULL pointer isn't valid, on Windows that will cause an access violation due to null ptr de-refpaulm

1 Answers

1
votes

That error will show when you're trying to free a non-allocated block of memory. If you weren't running this in valgrind, it would probably crash.

This will come from one of several reasons.

  1. You're not actually using a pointer. If you declare it wrong as you would in the first example below, you'll get the error because you're trying to free an int, not a pointer to an int.

    int * a, b;

    ...

    free(b);

  2. You're manually setting the value wrong. Pointers, like anything in C, can be cast, and assigned variables of a different type freely. This allows you to inadvertantly change the value of a pointer to actually being a literal numerical value. This will point to non-malloced memory, and fail.

    int * a;

    a = malloc(sizeof(int));

    (int) a = 4;

    free(a);

  3. A more specific example, but the instance in which the variable was created was previously destroyed, and the program has been executing long enough that it has since fallen out of the valgrind table and will no longer generate an error. This is a result of double-freeing. You're PROBABLY not encountering this.