【问题标题】:Memory leak in C program, can't see where to free memoryC程序中的内存泄漏,看不到在哪里释放内存
【发布时间】:2014-04-01 23:42:59
【问题描述】:

我正在编写一个 C 程序来生成密钥并在加密函数中对其进行测试。但是,由于我以前从未编写过 C 程序,而且我完全不习惯手动管理内存,所以我遇到了问题。我有内存泄漏,老实说,我不知道如何解决它。我知道我需要在某个时候释放内存,但直到我用完所有键并且在我用完所有键之前内存不足。用不同的语言编写程序不是一种选择,所以请不要建议。泄漏的代码如下所示,任何帮助将不胜感激。

编辑:我知道我没有调用 free 函数来释放内存。我看不到我可以把它放在哪里,因为我需要内存,直到我遍历所有键。将其放在循环之外并不能解决问题,因为泄漏发生在循环内部

第二次编辑:发布完整程序。由于 DES 加密函数(我没有写)的工作原理,我没有使用其他数据结构(即 bool 数组)的选项。

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

void dec2bin(bool *testaRR, bool *to_return, int convert);

int main(int argc, const char * argv[])
{

// insert code here...
bool testKey[56] = {
    0, 1, 0, 0, 0, 0, 0, 1,
    0, 1, 0, 0, 0, 0, 0, 1,
    0, 1, 0, 0, 0, 0, 0, 1,
    0, 1, 0, 0, 0, 0, 0, 1,
    0, 1, 0, 0, 0, 0, 0, 1,
    0, 1, 0, 0, 0, 0, 0, 1,
    0, 1, 0, 0, 0, 0, 0, 1
};
bool testKey2[56] = {//intuitive key reversed for testing
    1, 0, 0, 0, 0, 0, 1, 0,
     1, 0, 0, 0, 0, 0, 1, 0,
     1, 0, 0, 0, 0, 0, 1, 0,
     1, 0, 0, 0, 0, 0, 1, 0,
     1, 0, 0, 0, 0, 0, 1, 0,
     1, 0, 0, 0, 0, 0, 1, 0,
    1, 0, 0, 0, 0, 0, 1, 0
};
 bool output[64];

 bool input[64] = {//the reverse of below...  DES bits are numbered left to right, in order of least to most significant so we must enter the bit values in reverse.
     //forexample the binary vale of N is 01001110 but below is displayed as 01110010
 1, 0, 0, 0, 1, 1, 0, 0,//1
 0, 0, 0, 0, 1, 1, 0, 0,//0
 1, 1, 0, 0, 0, 0, 1, 0,//C
 1, 0, 1, 0, 0, 0, 1, 0,//E
 1, 1, 0, 0, 1, 0, 1, 0,//S
 0, 0, 1, 0, 1, 0, 1, 0,//T
 1, 0, 1, 0, 0, 0, 1, 0,//E
 0, 1, 1, 1, 0, 0, 1, 0 //N
 };
 int y = sizeof(input);
 printf("(Input MSG: ");
 for (int i = y-4; i >= 0; i-=4)
 printf("%X", input[i]+2*input[i+1]+4*input[i+2]+8*input[i+3]);//this is the conversion to    hex code
 printf(")\n");

/*
 use char[] to store the key as set of 
 */
/*bool input[64] = {//this is the given plaintext message in the intuitive order (opposite of what it is)   
    0, 1, 0, 0, 1, 1, 1, 0,//N
    0, 1, 0, 0, 0, 1, 0, 1,//E

    0, 1, 0, 1, 0, 1, 0, 0,//T
    0, 1, 0, 1, 0, 0, 1, 1,//S
    0, 1, 0, 0, 0, 1, 0, 1,//E
    0, 1, 0, 0, 0, 0, 1, 1,//C
    0, 0, 1, 1, 0, 0, 0, 0,//0
    0, 0, 1, 1, 0, 0, 0, 1 //1
};


int y = sizeof(input);
printf("(Input MSG: ");
for (int j = 0; j < y; j+=4)
    printf("%X", input[j+3]+2*input[j+2]+4*input[j+1]+8*input[j]);//this is the conversion to hex code
printf(")\n");*/
bool test [8];
bool returned[8];
char keyphrase [8];
keyphrase[7] = 0;

for(int start = 65; start<=90; start++)
{
     //dec2bin(test, returned, start);
 keyphrase[0] = start;
    for(int two = 65; two<=90; two++){
        keyphrase[1]=two;
        for(int three = 65; three<=90; three++){
            keyphrase[2]=three;
            for(int four = 65; four<=90; four++){
                keyphrase[3]=four;
                for(int five = 65;five<=90;five++){
                    keyphrase[4]=five;
                    for( int six = 65; six <=90; six++){
                        keyphrase[5]=six;
                        for(int seven = 65; seven <=90; seven++){
                            keyphrase[6]=seven;
                            printf("%s \n", keyphrase);
                        }

                            }}
                        }
                    }
                }
 //once i fix the memory leak I will be calling the EncryptDes Function here and checking the outputblk agains the given cipher text
}
free(keyphrase);

int k = sizeof(testKey);
printf("(Test Key: ");
for (int z = 0; z < k; z+=7)
    printf("%d", testKey[z+7]+2*testKey[z+6]+4*testKey[z+5]+8*testKey[z+4]+16*testKey[z+3]+32*testKey[z+2]+64*testKey[z+1]+ 128*testKey[z]);//this is the conversion to hex code
printf(")\n");

//loop on the key (starting at
EncryptDES(testKey, output, input, 0);
int x = sizeof(output);
printf("(Output MSG: ");
for (int i = 0; i < x; i+=4)
    printf("%X", output[i+3]+2*output[i+2]+4*output[i+1]+8*output[i]);//this is the conversion to hex code
printf(")\n");


return 0;
}
void dec2bin (bool *testaRR, bool *to_return, int convert)

{
 printf("%d : ", convert);
 printf("%c", convert);
 printf("\n ");

//bool testaRR [8];
for(int st = 0; st<8; st++){
    testaRR[st] = convert%2;
    to_return[7-st] = testaRR[st];
    //printf("%d :", 7-st);
   //printf(" %d spot ", st);
    convert = convert/2;
    //testaRR stores the arrays in one direction
    //to_return stores them in the other
    //Example:
    //65 = 01000001 testaRR least significant on the far right (m0st sig is in index 7)better for storage and keeping track of where the bits actually are in binary
    //65 = 10000010 to_return least significant on the far left (same as DES) (most significant bit is index 0) good for printing to screen
}

【问题讨论】:

  • 附带说明,没有必要在 C 中强制转换 malloc() 的返回值,因为存在从 void* 到任何其他指针类型的隐式转换(在 C++ 中这不适用)。无论如何强制转换只会在您没有 malloc 原型在范围内的情况下关闭编译器(阅读:以防您忘记#include &lt;stdlib.h&gt;),导致未定义的行为
  • 我不明白你为什么认为你首先有内存泄漏。循环内部没有内存泄漏。我认为您所说的“内存泄漏”是一些完全不同的错误。
  • 当它循环时我的计算机内存不足......当我不运行循环时它不会
  • 你怎么知道“你的电脑内存不足”?
  • 因为我看到可用内存从超过 4 GB 下降到大约 5 MB...我使用 iStatPro 进行监控

标签: c memory-management memory-leaks


【解决方案1】:

这里不需要动态内存管理。

开始

char keyphrase[8];
keyphrase[7]=0;

而不是你的malloc,你会很高兴的。您的最高数组索引是 7(终止 NUL),因此您需要一个包含 8 个项目 (0..7) 的数组。

如果您真的想使用malloc,只需在末尾添加free() 即可,但您需要将malloc 设置为8 个字符并将keyphrase[7] 设置为0 以执行终止NUL。

这是一个经过测试的版本:

#include <stdio.h>

/* compile with gcc -Wall -std=c99 keyphrase.c -o keyphrase */

int
main (int argc, char **argv)
{
  char keyphrase[8];
  keyphrase[7] = 0;
  for (int start = 65; start <= 90; start++)
    {
      //dec2bin(test, returned, start);
      keyphrase[0] = start;
      for (int two = 65; two <= 90; two++)
        {
          keyphrase[1] = two;
          for (int three = 65; three <= 90; three++)
            {
              keyphrase[2] = three;
              for (int four = 65; four <= 90; four++)
                {
                  keyphrase[3] = four;
                  for (int five = 65; five <= 90; five++)
                    {
                      keyphrase[4] = five;
                      for (int six = 65; six <= 90; six++)
                        {
                          keyphrase[5] = six;
                          for (int seven = 65; seven <= 90; seven++)
                            {
                              keyphrase[6] = seven;
                              printf ("%s \n", keyphrase);
                            }
                        }
                    }
                }
            }
        }
    }
}

【讨论】:

  • 这对我的回答有什么影响?
  • 刚刚尝试过这个,但程序又吃掉了我所有的记忆。不过谢谢
  • @DeadMG 我开始打字时你的答案不在那里。
  • @Jake - 问题可能是您缺少#include,因此它为printf 使用了错误的原型。我重新缩进了它并进行了我建议的更改,它对我来说运行得很好。
  • 我的程序中有#includes,我只是包含了我遇到问题的sn-p。我尝试了这种方法,但不幸的是我没有解决它。我将尝试 DeadMG 的答案。感谢您的建议!
【解决方案2】:

真正的问题是printf 的使用。你没有 NULL 终止keyphrase,所以每次你printf 都会溢出。

另外,为避免内存泄漏,只需将char *keyphrase = (char *)malloc(7); 替换为char keyphrase[8];。

【讨论】:

  • 我最初尝试只声明 char 关键字[7],但这也导致了内存泄漏。
  • 就像我说的,真正的问题是printf 调用。
  • 能否详细说明?
  • char keyphrase[7]没有导致内存泄漏。
  • @Jake:printf 的参数需要以空值结尾。您没有 NULL 终止 keyphrase。这就是您的程序无法运行的原因。
【解决方案3】:

您在第一行调用malloc,但我没有看到一个free 来释放您分配的内容。在所有循环完成后(即分配数据的使用完成)您必须调用free(keyphrase);

【讨论】:

  • 我意识到这一点。但是免费去哪里了?每次我把语句放进去,它都会抛出错误
  • 免费是这里最小的问题。
  • @Jake:为什么要在循环中为 char 分配整数值?
  • 因为我必须将我正在编写的程序从 Ascii 转换为二进制。即我存储字符的 ascii 数值,以便我可以将整数取出并将其转换为二进制值
  • 你只需要简单的if语句,你的做法是非常错误的;只看for循环的数量就说明了这一点。读一本关于 C 的好书。
【解决方案4】:

程序修改后的新答案。

您说您的程序正在使用所有内存'因为我正在观察可用内存从超过 4 GB 下降到大约 5 MB'。

我猜答案不是循环,而是这些行:

//loop on the key (starting at
EncryptDES(testKey, output, input, 0);
int x = sizeof(output);

我们看不到 EncryptDES 的来源或声明,但您没有将长度传递给它。如果0 是长度,这将解释它。

然而,下一行表明output 是一个 64 字节(而不是 2 个字符串)的数组。但是EncryptDES 无法知道这一点。

我建议你在valgrind 下运行整个事情以了解发生了什么。

【讨论】:

  • 我想明白了。显然它正在发生,因为我试图将所有生成的键打印到屏幕上。我没有意识到 printf 是如此的资源消耗。一旦我停止尝试打印每个键,我的问题就消失了。不过,感谢您的帮助!
猜你喜欢
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 2012-10-11
  • 1970-01-01
相关资源
最近更新 更多