damnever
damnever

Reputation: 14737

Why my C code got error in Windows? Linux is ok

There is my C code, it is a leetcode problem, and I got "Runtime Error". So I recompile in VS2013, the problem is free(++tmp), why? I can't get it, I writen C code like that, just want to known more things about pointer.

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

/*   Add binary.
 *   a = "11", b = "1"
 *   result = "100"
 */

char *add_binary(char *a, char *b);

int main()
{
    printf("%s\n", add_binary("10", "1"));
    printf("%s\n", add_binary("1111", "1111"));
    return 0;
}

char *add_binary(char *a, char *b)
{
    int alen = 0, blen = 0, sum = 0;
    int len;
    char *tmp, *result;

    while(*a++) alen++;
    while(*b++) blen++;
    a -= 2;
    b -= 2;
    len = alen > blen ? alen : blen;
    tmp = (char *)malloc(len*sizeof(char));
    printf("%p\n", tmp);

    while(*a || *b){
        if(*a){
            sum += *a - '0' + 0;
            a--;
        }
        if(*b){
            sum += *b - '0' + 0;
            b--;
        }
        if(sum > 1){
            *tmp++ = 3 == sum ? '1' : '0';
            sum = 1;
        } else {
            *tmp++ = 1 == sum ? '1' : '0';
            sum = 0;
        }
    }
    *tmp = '\0';

    len += 1 == sum ? 1 : 0;
    result = (char *)malloc(len*sizeof(char));
    if(1 == sum){
        *result++ = '1';
    }
    while(*(--tmp)){
        *result++ = *tmp;
    }
    *result = '\0';
    printf("%p\n", tmp);
    free(++tmp);
    tmp = NULL;
    return (result-len);
}

Upvotes: 0

Views: 79

Answers (4)

John Bode
John Bode

Reputation: 123478

free expects its argument to be the same pointer value that was returned from a previous malloc or realloc call. If you modify that pointer value before passing it to free, then the behavior is undefined and Bad Things can happen (this is why it appears to work for one platform and breaks on another; in truth, it's broken for both).

You'll need to preserve the pointer values returned from your malloc calls:

char *tmp, *tmpOrig;
...
tmp = tmpOrig = malloc(len * sizeof *tmpOrig); // note no cast, operand of sizeof
...
/**
 * modify tmp to your heart's desire
 */
...
free( tmpOrig );

You'll need to do the same thing for result.

You should not cast the result of malloc, unless you are working with a pre-C89 compiler. It's unnecessary, and under C89/C90 compilers can mask a bug.

Upvotes: 0

Martin James
Martin James

Reputation: 24857

Stop modifying the mallocated pointer before freeing it. If you want to use pointer arithmetic, eg '*tmp++', then keep a copy of the original so that the space can be freed.

I have no clue why you would do 'free(++tmp);'. It makes no sense though, by that time, you've already totally shagged up tmp by incrementing it in the while loop:(

Edit: BTW, you've screwed 'result' as well. You are returning a malloced and bodged pointer that cannot be correctly freed by the caller.

Whatever 'clever' thing you are attempting with the pointer manipulations, stop it. It's too easy to get it wrong!

Upvotes: 1

Dan
Dan

Reputation: 393

Here is a slightly more detailed response from the other answer.

The pointer is an address for which you allocate memory. When you pass in an address to free that has been previously malloc'd there is no problem. The problem is that you are not passing in the address of a malloc'd space. You are passing in the address of something that is potentially within a malloc'd space and as such cannot be freed.

Upvotes: 0

ouah
ouah

Reputation: 145839

You can only pass to free the resulting pointer value of malloc:

tmp = (char *)malloc(len*sizeof(char));

then

free(tmp);

is OK.

But free(++tmp) or free(tmp + 42) is not OK and invokes undefined behavior.

Upvotes: 6

Related Questions