开发者

freeing possible memory leak

I have been thinking in this for a while but I'm not sure if it's "safe" and possible.

Imagine something like this:

void genLeaks(void)
{
 char* charLeakAddr;
 charLeakAddr = (char*)malloc(sizeof(char) * 10);
 strcpy(charLeakAddr, "Hello World");
}

As I understand this will create a memory leak because charLeakAddr is not released ( free (charLeakAddr); ).

Now in main :

int main(void)
{
 genLeaks();

 ??????? 

 return 0;
}

In the place marked with ??????? is there a way to create some kind of function that frees the memory allocated by charLeakAddr?

Thanks for your time.

Sorry but, how can I do to make the code good looking in the post :S ?

Thanks for your answers.

Somehow I produced this code and it seems to work ( I tested it in GCC with Code::Blocks in both Linux and Windows) Please take a look at it. Is it correct? or it is just crazy to try something like it?

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

#define LEAKS_PATH_FILE               "leaks.txt"
#define WIN_ERASE_LEAKS_FILE_COMMAND  "erase leaks.txt"
#define UNIX_ERASE_LEAKS_FILE_COMMAND "rm leaks.txt"

#define __ASM__LEAK__DELETER__DEBUG

#define __UNIX__DEBUG__

unsigned int LEAKS = 0;

void regLeakAddr(void* memPtr, const char* fileName)
{
 FILE* arch;

 #ifdef __ASM__LEAK__DELETER__DEBUG
  printf("\nMemory Leak : 0x%x\n", (void*)memPtr);
 #endif

 arch = fopen(fileName, "a");

 if(arch)
 {
  fprintf(arch, "%d", (void*)memPtr);
  fprintf(arch, "%c", '\n');
  fclose(arch);
  LEAKS++;
 }
 else
  printf("ERROR IN FILE leaks.txt\n");
}

void assemblyDeleter(int numAddr)
{
 #ifdef __ASM__LEAK__DELETER__DEBUG
  printf("\nOnassemblyDeleter : 0x%x\n\n", numAddr);

  #ifdef __UNIX__DEBUG__
   getchar();
  #else
   system("pause");
  #endif
 #endif

 char* deleter;
 int*  ptr = &numAddr;

 printf("\n======> 0x%x\n\n", *ptr);
 printf("\n======> 0x%x\n\n", deleter);

 if((c开发者_开发知识库har*)*ptr > deleter)
 {
  printf("(ptr > deleter) : Offset : 0x%x\n", ((char*)*ptr - deleter));
  deleter += ((char*)*ptr - deleter);
 }
 else
 {
  printf("(ptr < deleter) : Offset : 0x%x\n", (deleter - (char*)*ptr));
  deleter += ((char*)*ptr - deleter);
 }

 printf("deleter =========> 0x%x\n", deleter);

 #ifdef __ASM__LEAK__DELETER__DEBUG
  puts(deleter);
 #endif

 free(deleter);

 #ifdef __ASM__LEAK__DELETER__DEBUG
  puts(deleter);
 #endif

 deleter = NULL;
 ptr     = NULL;
}

void freeMemory(void)
{
 if(LEAKS == 0)
 {
  #ifdef __ASM__LEAK__DELETER__DEBUG
   printf("NO LEAKS\n");
  #endif
  return;
 }

 FILE* arch;
 int   addr;
 int i;

 arch = fopen(LEAKS_PATH_FILE, "r");

 if(arch == NULL)
 {
  #ifdef __ASM__LEAK__DELETER__DEBUG
   printf("Error on file...\n");
  #endif
  return;
 }

 for(i = 0; i<LEAKS; i++)
 {
  fscanf(arch, "%d", &addr);
  assemblyDeleter(addr);
 }

 fclose(arch);

 #ifdef __UNIX__DEBUG__
  system(UNIX_ERASE_LEAKS_FILE_COMMAND); 
 #else
  system(WIN_ERASE_LEAKS_FILE_COMMAND); 
 #endif
}

void genLeakTrick(char** msg)
{
 *msg = (char*)malloc(sizeof(char) * 17);
 strcpy(*msg, "Hello World again");
 printf("\n%s\n", *msg);
}

void genLeaks(void)
{
 char* charLeakAddr;
 charLeakAddr = (char*)malloc(sizeof(char) * 10);
 strcpy(charLeakAddr, "Hello World");
 printf("\n%s\n", charLeakAddr);
 //free(charLeakAddr);
 regLeakAddr(charLeakAddr, LEAKS_PATH_FILE);

 char* charLeakAddr2;
 genLeakTrick(&charLeakAddr2);
 //free(charLeakAddr2);
 regLeakAddr(charLeakAddr2, LEAKS_PATH_FILE);
}

int main(void)
{
 genLeaks();

 freeMemory();

 return 0;
}


No, there is no way to free that memory. It's permanently lost (unless you can somehow find the pointer that was originally returned by malloc).

You can always just free it in genLeak since it's not being used for anything after that. If you return the pointer though, someone else is going to have to free it after it's used.

That's why in C library documentation whenever a pointer is returned, they tell you who the pointer is owned by and if you have to free it or not.


No way, until the genleak() return type is void. Modifying the return type and if the function returns a reference of charLeakAddr, it would be possible.

char* genleak()
{
    char* charLeakAddr;
    charLeakAddr = (char*)malloc(sizeof(char) * 10);
    strcpy(charLeakAddr, "Hello World");

    return charLeakAddr ;
}

int main()
{
     genleak(); // Now also not possible, since the return value is not collected.
     char* temp = genleak();

     free temp;  // Deallocating the resources acquired using malloc
     return 0;
}

Edit:

In the posted snippet, charLeakAddr goes out of scope up on return of function call genleak(). Thus, making the resources stay there on the free way making no process to access the leaked sources. How about adding a global variable ?

char* globalVar = NULL ;
void genleak()
{
    char* charLeakAddr;
    charLeakAddr = (char*)malloc(sizeof(char) * 10);
    // ....
    globalVar = charLeakAddr ;
}

int main()
{
    // .....
    genleak();
    free globalVar ;
}

And in genleak(), assign the value of where charLeakAddr is pointing to it. And then, the program can perform a free operation on it.


Yes, there's a way, that's called garbage collector. You can read this and this for some heads up. Basically if all your program is compiled/linked with the garbage collector, you might be able to do things like

gc.collect()

to claim back all leaked memory.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜