检测到glibc:双重免费或腐败

时间:2013-06-27 12:57:56

标签: c++

我将解释我所做的简短编码步骤以及我面临问题的区域

的main.cpp

int main()
{
    int cnt_map,i=1,value;

   /* My question is about this char pointer "key" */ 
    char *key =(char*)malloc(sizeof(char) * 25);

   if(key!=NULL)
   {
     printf("Key value is not NULL,its value is:%x\n",key) ;
     cout<< "Enter the number of elements required in container map"<<endl;
     cin >> cnt_map;
     for (i=1;i<=cnt_map;i++)
     {
       cout << "Enter the key : ";
       cin >>key;
       cout << "Enter the key value:" ;
       cin >>value;
       printf("value pointed by ptr key: %s, value in ptr: %x\n", key,key);
       c -> add_map1(key,value); //Function inserts value to map container
       key+=sizeof(key);
     }
     c -> size_map1();           //Function displays size of map container
     c -> display_map1();        //Function displays contents of map container
  if(key)
  {
    printf("FINALLY:value pointed by ptr key: %s, value in ptr: %x,size:%d\n",key, key, sizeof(key));
    free(key);
  } 
 }
return 0;
}

在尝试编译并运行上面的代码时,我能够成功编译代码,但在尝试运行应用程序时“检测到glibc:双重释放或损坏”。

现在我的问题是我创建了一个字符指针(char *key =(char*)malloc(sizeof(char) * 25);) 并使用malloc为其成功分配了内存。完成我的过程后,当我尝试释放该指针时,我得到双重免费或损坏错误。我了解到,应该最终释放任何带有malloc / calloc的变量分配内存。请告诉我为什么这会出现错误,为什么我不应该这样做?请告诉我char* key内存操作是如何进行的(如果可能,请以图片形式展示)。

注意:上面提到的代码不是完整的代码,我刚刚解释了我遇到问题的地方, 如果我没有释放指针变量,我的应用程序运行成功。

非常感谢任何帮助。非常感谢提前。

4 个答案:

答案 0 :(得分:7)

通过这样做:

key+=sizeof(key);

您的key变量不再指向您分配的内存的开头。您必须将原始指针传递给free()。您需要将原始指针存储在另一个变量中,以便最后能够正确free()

(你可以简单地删除那一行 - 我不知道它在做什么,因为sizeof(key)是4或8.我怀疑它是多余的。)

答案 1 :(得分:5)

这是因为这一行:key+=sizeof(key);key不包含与malloc返回的地址相同的地址。

例如:

char *key =(char*)malloc(sizeof(char) * 25);

假设malloc返回地址20000(完全是愚蠢的地址,仅用于示例)。

现在你正在做key+=sizeof(key);,所以key = 20000 + 4 = 20004.问题是你正在尝试释放key,它指向地址20004而不是20000。

为了解决这个问题,请尝试以下方法:

int main()
{
    int cnt_map,i=1,value;
    char *key_save;

   /* My question is about this char pointer "key" */ 
    char *key =(char*)malloc(sizeof(char) * 25);

    key_save = key;
   if(key!=NULL)
   {
     printf("Key value is not NULL,its value is:%x\n",key) ;
     cout<< "Enter the number of elements required in container map"<<endl;
     cin >> cnt_map;
     for (i=1;i<=cnt_map;i++)
     {
       cout << "Enter the key : ";
       cin >>key;
       cout << "Enter the key value:" ;
       cin >>value;
       printf("value pointed by ptr key: %s, value in ptr: %x\n", key,key);
       c -> add_map1(key,value); //Function inserts value to map container
       key+=sizeof(key);
     }
     c -> size_map1();           //Function displays size of map container
     c -> display_map1();        //Function displays contents of map container
  if(key)
  {
    printf("FINALLY:value pointed by ptr key: %s, value in ptr: %x,size:%d\n",key, key, sizeof(key));
    free(key_save);
  } 
 }
return 0;
}

答案 2 :(得分:1)

只需删除该行:

key+=sizeof(key);

key不是指向字符串数组的指针,它是指向单个字符串的指针。每次递增时,都会减少字符串中的可用空间。第一次读取密钥时,有25个字节可用。下一次,您将key增加了4或8个字节,但分配的空间的末尾没有改变,所以现在只有21或17个字节可用。第三次它只有17或9个字节,依此类推。经过几次迭代后,您将增加key超过您分配的内存块的末尾,它将开始写入未分配的内存(或分配给其他数据结构的内存)。这是未定义的行为,很可能会导致程序出现不可预测的故障。

由于您使用的是C ++,因此您应该使用std::string代替char[]代替字符串,而std::vector代替普通数组。这些数据结构会根据需要自动扩展,因此可以避免像这样的缓冲区溢出。

答案 3 :(得分:0)

这不考虑您的代码,但我在Reader writer问题(操作系统)http://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem中遇到了同样的问题。

这是由于文件指针是全局的,所以每当任何读者试图读取时,在黑白中另一个读取读取和关闭文件指针,这样当另一个未完成读取的读取器尝试在读取后关闭文件指针。所以发生的事情是文件指针已经关闭它没有指向任何文件。 解决方案我用过。 它不是声明文件指针全局,而是将它声明为读取器函数的本地,或者你可以检查文件指针是否为NULL,如果为NULL则不要关闭文件指针。

#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<string.h>
#include<stdlib.h>
sem_t x,wsem;
int rc=0;
char ch;
char str[20];
void *reader(void *);
void *writer(void *);


int main()
{
 int nw,nr,i=0,j=0;
 pthread_t w[10],r[10];
 sem_init(&x,0,1);
 sem_init(&wsem,0,1);
 rc=0;
 printf("Enter the no of readers:");
 scanf("%d",&nr);
 printf("Enter the no of writers");
 scanf("%d",&nw);
 while(i<nw || j<nr) 
 {

  if(i<nw)
  {
pthread_create(&w[i],NULL,writer,(void *)i);

i++;
  }
  if(j<nr)
  {
pthread_create(&r[j],NULL,reader,(void *)j);

    j++;
  }
 }
 for(i=0;i<nw;i++)
 {
pthread_join(w[i],NULL); 
 }
 for(j=0;j<nr;j++)
 {
pthread_join(r[j],NULL);
 }

 return 0;
}

void *reader(void *arg)
{
 FILE *fptr;
 sem_wait(&x);
 rc++;
 if(rc==1)
  sem_wait(&wsem);
 sem_post(&x);

 printf("\nreader %d:",arg);
 fptr=fopen("temp.txt","r+");
 while(fgets(str,10,fptr)!=NULL)
 {
  printf("%s",str);
 }
 printf("\n");
 fclose(fptr);
 sem_wait(&x);
 rc--;
 if(rc==0)
    sem_post(&wsem);
 sem_post(&x);
}


void *writer(void *arg)
{
 FILE *fptr1;
 sem_wait(&wsem);  
 printf("\nwriter-%d:\n",arg);
 fptr1=fopen("temp.txt","a+");
 printf("enter the string:");
 scanf("%s",str);
 fputs(str,fptr1);
 fclose(fptr1);  
 sem_post(&wsem);
}