In c program, why free memory of string (which copy from strcpy) in osx is not woking? [duplicate]

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-08 02:20:14

问题


my osx version is 10.12,

when I copy string from origin string , then free it, it's not working,

But in linux(centos 6.2) is ok, I print copy is invalid.

I don't find the reason, It's really confused me.

here is code:

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

int main(){
 char *copy;
 char *origin = "tutorialspoint";
 copy = (char *) malloc(15);
 strcpy(copy, origin);

 free(copy); //not working
 printf("string = %s,  Address = %u\n", copy, copy);
 printf("origin = %s,  Address = %u\n", origin, origin);
 return(0);
}

most strange thing is when I free memory for origin, copy's memory also be freed

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

int main(){
 char *copy;
 char *origin = "tutorialspoint";
 copy = (char *) malloc(15);
 strcpy(copy, origin);

 free(origin); //working for copy too 
 printf("string = %s,  Address = %u\n", copy, copy);
 printf("origin = %s,  Address = %u\n", origin, origin);
 return(0);
}

回答1:


Your problem is your placement of free(copy), move it after you make use of copy, otherwise you are attempting to read from a variable that has already been freed (an uninitialized value - invoking Undefined Behavior), (as @Pras correctly notes you free (copy), not free (origin), e.g.

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

int main(){
    char *copy;
    char *origin = "tutorialspoint";
    copy = malloc (strlen (origin) + 1);
    strcpy(copy, origin);

    printf("string = %s,  Address = %p\n", copy, (void *)copy);
    printf("origin = %s,  Address = %p\n", origin, (void *)origin);
    free(copy);  /* works find here */
    return(0);
}

note: use of %p for the pointer address.

You should also validate ALL memory allocations, e.g.

    if (!(copy = malloc (strlen (origin) + 1))) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

Example Use/Output

$ ./bin/origin
string = tutorialspoint,  Address = 0xbe3010
origin = tutorialspoint,  Address = 0x400710

copy is freed

Continuing from your comment, copy is in fact freed. How can you tell? You run you code through a memory/error checking program like valgrind, e.g.

$ valgrind ./bin/origin
==10564== Memcheck, a memory error detector
==10564== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10564== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==10564== Command: ./bin/origin
==10564==
string = tutorialspoint,  Address = 0x51d8040
origin = tutorialspoint,  Address = 0x400710
==10564==
==10564== HEAP SUMMARY:
==10564==     in use at exit: 0 bytes in 0 blocks
==10564==   total heap usage: 1 allocs, 1 frees, 15 bytes allocated
==10564==
==10564== All heap blocks were freed -- no leaks are possible
==10564==
==10564== For counts of detected and suppressed errors, rerun with: -v
==10564== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

As you can see, all memory allocated had in fact been freed and -- no leaks are possible and there were 0 errors from 0 contexts.




回答2:


In you program origin is not allocated on heap, so freeing it can result in undefined behavior




回答3:


Running the first example will in many cases still print out the tutorialspoint string for both copy and origin. free() does not modify the memory in the location you malloc'ed and it also does not change the address of the pointer to origin, so in theory you can still see still see the value by printing out copy. But, you should NOT depend on this. After running free() you should consider the pointer unusable until reassigned as another process may overwrite that memory space.

The second example prints for similar reasons, but origin is a heap pointer and can not be free'd. ONLY malloc'ed pointers can be safely free'd using free()




回答4:


Do you wonder what should happen when your computer behaves in an... undefined... manner? Should it:

  • a/ emit an error message,
  • b/ crash,
  • c/ read your mind and function as you intended, or
  • d/ behave in an undefined manner?

Hint: the first three options seem very much defined, don't they?

Your code invokes undefined behaviour. Namely, these two lines in your first example:

printf("string = %s,  Address = %u\n", copy, copy);
printf("origin = %s,  Address = %u\n", origin, origin);

... and this line, in your second example:

free(origin);
  • You should be using %p to print a void * (as David pointed out). Using %u to print anything but an unsigned int is a lie to printf, which causes undefined behaviour.
  • You shouldn't use (i.e. attempt to print the string it used to point to) copy after you've freed it; that's also undefined behaviour.
  • You shouldn't free anything that wasn't returned by malloc, calloc or realloc; again, undefined behaviour.

Note that undefined behaviour may appear to work coincidentally, hence the string that the freed object once contained may still appear to exist; as programmers we don't like relying upon coincidence, but it just so happens that the undefined nature of the behaviour might correspond to your code working coincidentally. It might also coincidentally (or not) fail subtly or catastrophically in other situations. Hence, we should avoid undefined behaviour.



来源:https://stackoverflow.com/questions/43861554/in-c-program-why-free-memory-of-string-which-copy-from-strcpy-in-osx-is-not-w

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!