简体   繁体   English

使用Valgrind检查后,如何查找和删除C程序中的内存泄漏和错误

[英]How to find & remove memory leaks and errors in my C program after checked it with Valgrind

After checked my code with Valgrind, it shows a lot of error messages and information and I am not sure about how to find and remove the errors in code? 用Valgrind检查我的代码后,它显示了很多错误消息和信息,我不确定如何查找和删除代码中的错误?

My source code is as follows. 我的源代码如下。

myheader.h myheader.h

 #include<stdlib.h>
 #define MAX 15
 typedef enum
 {
  METROPOLITAN_AREA,
  TOURIST_AREA,
 }area_type_t;

 typedef struct
 {
  int population;
  int area;
 }metropolitan_t;

 typedef struct
 {
  char *type_place;
  char *near_airport;
 }tourist_t;

 typedef struct
 {
  char *name;
  char *country;
  area_type_t area_t;
  union
  {
      metropolitan_t metro;
      tourist_t   tourist;
  }u;

 }*place_t;
 extern void get_input(place_t);

getinput.c getinput.c

#include<myheader.h>
void get_input(place_t place)
{
 int check=1;
 int num,i,ch;
 printf("\nEnter the no of records : \n");
 scanf("%d",&num);
 place=(place_t)malloc(sizeof(place_t)*num);
 if(NULL==place)
 {
  printf("\nMemory allocation failed\n");
  exit(1);
 }
 for(i=0;i<num;i++)
 {
  printf("\nEnter the place name : ");
  place->name=(char *)malloc(sizeof(char)*MAX);
  if(NULL==place->name)
  {
   free(place);
   printf("\nMemory allocation failed\n");
   exit(1);
  }
  scanf("%s",place->name);
  printf("\nEnter the coutry name : ");
  place->country=(char *)malloc(sizeof(char)*MAX);
  if(NULL==place->country)
  {
   free(place);
   free(place->name);
   printf("Memory allocation failed\n");
   exit(1);
  }
  scanf("%s",place->country);
   printf("\nPlease Enter '0' if the place is Metropolitan, '1' if the place Tourist place\n");
   scanf("%d",&ch);
  while(check)
  {
   switch(ch)
   {
    case 0:
     check=0;
     place->area_t=METROPOLITAN_AREA;
     break;
    case 1:
     check=0;
     place->area_t=TOURIST_AREA;
      break;
    default:
     printf("\nPlease enter valid choice \n");
   }
  }
  if(place->area_t==METROPOLITAN_AREA)
  {
    printf("\nEnter the population of the place : ");
    scanf("%d",&(place->u.metro.population));
    printf("\nEnter the area of place :"); 
    scanf("%d",&(place->u.metro.area));
  } else
  {
   printf("\nEnter the nearest airport name : ");
   place->u.tourist.near_airport=(char *)malloc(sizeof(char)*MAX);
   if(NULL==place->u.tourist.near_airport)
   {
    printf("Memory allocation failed\n");
    exit(1);
   }
   scanf("%s",(place->u.tourist.near_airport));
   printf("\nEnter the type of tourist spot : ");
   place->u.tourist.type_place=(char *)malloc(sizeof(char)*MAX);

   if(NULL==place->u.tourist.type_place)
   {
    printf("Memory allocation failed\n");
    exit(1);
   }
   scanf("%s",(place->u.tourist.type_place));
  }
  check=1;
  place++;
 }
}

main.c main.c中

#include"myheader.h"
int main()
{
 place_t place;
 get_input(place);
 return 0;
}

Command-line transcript 命令行脚本

 bash-3.00$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes a.out
 ==13514== Memcheck, a memory error detector.
 ==13514== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
 ==13514== Using LibVEX rev 1575, a library for dynamic binary translation.
 ==13514== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.
 ==13514== Using valgrind-3.1.1, a dynamic binary instrumentation framework.
 ==13514== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
 ==13514== For more details, rerun with: -v
 ==13514==

 Enter the no of records :
 2

 Enter the place name : Banglore

 Enter the coutry name : India

 Please Enter '0' if the place is Metropolitan, '1' if the place Tourist place
 0
 ==13514== Invalid write of size 4
 ==13514==    at 0x400789: get_input (getinput.c:43)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D040 is 0 bytes after a block of size 16 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x400637: get_input (getinput.c:8)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514== Invalid read of size 4
 ==13514==    at 0x4007BB: get_input (getinput.c:53)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D040 is 0 bytes after a block of size 16 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x400637: get_input (getinput.c:8)
 ==13514==    by 0x4005E8: main (main.c:5)

 Enter the population of the place : 303030

 Enter the area of place :2500
 ==13514==
 ==13514== Invalid write of size 8
 ==13514==    at 0x40068C: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D058 is not stack'd, malloc'd or (recently) free'd
 ==13514==
 ==13514== Invalid read of size 8
 ==13514==    at 0x400693: get_input (getinput.c:18)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D058 is not stack'd, malloc'd or (recently) free'd
 ==13514==
 ==13514== Invalid read of size 8
 ==13514==    at 0x4006BF: get_input (getinput.c:24)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D058 is not stack'd, malloc'd or (recently) free'd

 Enter the place name : London

==13514==
 ==13514== Invalid write of size 8
 ==13514==    at 0x4006EE: get_input (getinput.c:26)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D060 is 16 bytes before a block of size 15 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514== Invalid read of size 8
 ==13514==    at 0x4006F6: get_input (getinput.c:27)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514== Invalid read of size 8
 ==13514==    at 0x4006F6: get_input (getinput.c:27)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D060 is 16 bytes before a block of size 15 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514== Invalid read of size 8
 ==13514==    at 0x40072F: get_input (getinput.c:34)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D060 is 16 bytes before a block of size 15 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)

 Enter the coutry name : London

 Please Enter '0' if the place is Metropolitan, '1' if the place Tourist place
 1
 ==13514==
 ==13514== Invalid write of size 4
 ==13514==    at 0x40079D: get_input (getinput.c:47)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D068 is 8 bytes before a block of size 15 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)

 ==13514==
 ==13514== Invalid write of size 8
 ==13514==    at 0x40082F: get_input (getinput.c:62)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D078 is 8 bytes inside a block of size 15 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514== Invalid read of size 8
 ==13514==    at 0x400837: get_input (getinput.c:63)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D078 is 8 bytes inside a block of size 15 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514== Invalid read of size 8
 ==13514==    at 0x40085B: get_input (getinput.c:68)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==  Address 0x4A2D078 is 8 bytes inside a block of size 15 alloc'd
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)

 Enter the nearest airport name : London

 Enter the type of tourist spot : Entertainment

 ==13514==
 ==13514== ERROR SUMMARY: 13 errors from 12 contexts (suppressed: 4 from 1)
 ==13514== malloc/free: in use at exit: 106 bytes in 7 blocks.
 ==13514== malloc/free: 7 allocs, 0 frees, 106 bytes allocated.
 ==13514== For counts of detected errors, rerun with: -v
 ==13514== searching for pointers to 7 not-freed blocks.
 ==13514== checked 75,768 bytes.
 ==13514==
 ==13514==
 ==13514== 15 bytes in 1 blocks are indirectly lost in loss record 1 of 7
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40088A: get_input (getinput.c:70)
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40088A: get_input (getinput.c:70)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514==
 ==13514== 15 bytes in 1 blocks are definitely lost in loss record 2 of 7
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40082E: get_input (getinput.c:62)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514==
 ==13514== 15 bytes in 1 blocks are definitely lost in loss record 3 of 7
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x4006ED: get_input (getinput.c:26)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514==
 ==13514== 15 bytes in 1 blocks are definitely lost in loss record 4 of 7
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514==
 ==13514== 15 bytes in 1 blocks are indirectly lost in loss record 5 of 7
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x4006ED: get_input (getinput.c:26)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514==
 ==13514== 15 bytes in 1 blocks are indirectly lost in loss record 6 of 7
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x40068B: get_input (getinput.c:17)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514==
 ==13514==
 ==13514== 61 (16 direct, 45 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 7
 ==13514==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
 ==13514==    by 0x400637: get_input (getinput.c:8)
 ==13514==    by 0x4005E8: main (main.c:5)
 ==13514==
 ==13514== LEAK SUMMARY:
 ==13514==    definitely lost: 61 bytes in 4 blocks.
 ==13514==    indirectly lost: 45 bytes in 3 blocks.
 ==13514==      possibly lost: 0 bytes in 0 blocks.
 ==13514==    still reachable: 0 bytes in 0 blocks.
 ==13514==         suppressed: 0 bytes in 0 blocks.

How can I resolve this and make my program more memory-efficient? 如何解决这个问题并使我的程序更节省内存? Is there anything wrong in the malloc() statements that I used? 我使用的malloc()语句有什么问题吗?

The first thing to do is get rid of all the memory error(buffer overruns). 首先要做的是摆脱所有内存错误(缓冲区溢出)。 The first error occurs in get_input.c at line 45, so go to that line and figure out what's going wrong. 第45行的get_input.c中发生了第一个错误,所以转到该行并找出出错的地方。

One thing that's surely going wrong is this 有一件事肯定是错的

 place=(place_t)malloc(sizeof(place_t)*num);

You're allocating a place_t , however you have defined a place_t as this: 你正在分配一个place_t,但是你已经定义了一个place_t:

typedef struct
{

 }*place_t;

ie a place_t is just a pointer. 即place_t只是一个指针。 That means that eg malloc(sizeof(place_t)) just allocates space for a pointer, not for a whole place_t. 这意味着例如malloc(sizeof(place_t))只为指针分配空间,而不是为整个place_t分配空间。 Don't hide structs names as pointers with a typedef, but if you must, change your malloc statement to 不要将结构名称隐藏为带有typedef的指针,但如果必须,请将malloc语句更改为

     place=(place_t)malloc(sizeof *place)*num);

Another problem is that you free() the struct and afterwards try to access a member inside it, which is invalid. 另一个问题是你释放()结构,然后尝试访问其中的成员,这是无效的。

free(place);
free(place->name);

You have to do it in this order 你必须按此顺序进行

free(place->name);
free(place);

You are also leaking memory eg here: for(i=0;iname=(char *)malloc(sizeof(char)*MAX); 你也在泄漏内存,例如:for(i = 0; iname =(char *)malloc(sizeof(char)* MAX);

What happens the 2. time in this loop ? 在这个循环中2.时间会发生什么? You assign to place->name , losing the pointer to the memory you allocated in the first iteration of the loop. 您分配到place->name ,丢失指向您在循环的第一次迭代中分配的内存的指针。 Maybe you meant to use place[num] inside the loop as you do try to allocate many place_t's in the place=(place_t)malloc(sizeof(place_t)*num); 也许你打算在循环中使用place [num],因为你试图在place =(place_t)malloc(sizeof(place_t)* num)中分配许多place_t; statement. 声明。

The problem isn't so much the malloc statements, but rather the order in which you're freeing the memory up once you're finished with it. 问题不在于malloc语句,而是在你完成它之后释放内存的顺序。

eg 例如

free(place);
free(place->name);

should be 应该

free(place->name);
free(place);

otherwise memory allocated to name won't be freed. 否则将释放分配给name内存。

Similarly, calling free(place); 同样, free(place); wont free memory allocated in place->name=(char *)malloc(sizeof(char)*MAX); 不会释放释放的内存place->name=(char *)malloc(sizeof(char)*MAX);

You must manually free the memory allocated to each Malloc statement. 您必须手动释放分配给每个Malloc语句的内存。

It's always best to check whether pointers to memory locations are null before using them again with malloc . 在使用malloc再次使用它们之前,最好先检查指向内存位置的指针是否为null

If they're not null then free them and then set them to null . 如果它们不为nullfree它们然后将它们设置为null This will help in ensuring that you don't have memory leaks. 这有助于确保您没有内存泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM