освобождение от возможной утечки памяти - PullRequest
0 голосов
/ 15 марта 2011

Я долго об этом думал, но не уверен, что это "безопасно" и возможно.

Представьте себе что-то вроде этого:

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

Насколько я понимаю, это приведет к утечке памяти, поскольку charLeakAddr не освобождается (free (charLeakAddr);).

Сейчас в основном:

int main(void)
{
 genLeaks();

 ??????? 

 return 0;
}

В месте, отмеченном значком ??????? Есть ли способ создать какую-то функцию, которая освобождает память, выделенную charLeakAddr?

Спасибо за ваше время.

Извините, но как мне сделать так, чтобы код выглядел хорошо в посте: S?

Спасибо за ваши ответы.

Каким-то образом я создал этот код, и он, кажется, работает (я тестировал его в GCC с Code :: Blocks в Linux и Windows). Пожалуйста, посмотрите на него. Это правильно? или просто безумно пробовать что-то подобное?

#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((char*)*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;
}

Ответы [ 3 ]

1 голос
/ 15 марта 2011

Нет, нет способа освободить эту память. Он навсегда потерян (если только вы не можете найти указатель, который был первоначально возвращен malloc).

Вы всегда можете просто освободить его в genLeak, так как после этого он ни для чего не используется. Однако, если вы вернете указатель, кому-то еще придется освободить его после его использования.

Вот почему в документации библиотеки C при каждом возвращении указателя сообщается, кому принадлежит указатель и нужно ли его освобождать или нет.

0 голосов
/ 15 марта 2011

Да, есть способ, который называется сборщик мусора. Вы можете прочитать это и это для некоторых руководителей. По сути, если вся ваша программа скомпилирована / связана с сборщиком мусора, вы можете делать что-то вроде

GC.Collect ()

чтобы вернуть себе утечку памяти.

0 голосов
/ 15 марта 2011

Нет, пока тип возврата genleak() не станет void.Изменение типа возврата, и если функция возвращает ссылку charLeakAddr, это будет возможно.

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;
}

Редактировать:

В опубликованном фрагменте charLeakAddr выходит за рамки при возврате вызова функции genleak().Таким образом, создание ресурсов остается на свободном пути, не делая процесс доступа к утечкам.Как насчет добавления глобальной переменной?

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

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

А в genleak() присвойте значение, на которое указывает charLeakAddr.И тогда программа может выполнить на нем бесплатную операцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...