3

我将解释我已完成的简短编码步骤以及我面临问题的区域

主文件

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 指针(char *key =(char*)malloc(sizeof(char) * 25);)并使用 malloc 成功为其分配了内存。在我尝试释放该 char 指针时完成我的过程后,我得到双重释放或损坏错误。我了解到,任何使用 malloc/calloc 分配内存的变量最终都应该被释放。请告诉我为什么会出现这个错误,为什么我不应该这样做?请告诉我内存操作是如何进行的char* key(如果可能的话)。

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

4

4 回答 4

7

通过做这个:

key+=sizeof(key);

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

(您也许可以简单地删除该行 - 我不确定它在做什么,因为它sizeof(key)是 4 或 8。我怀疑它是多余的。)

于 2013-06-27T13:00:13.363 回答
5

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

例如:

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

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

现在你正在做key+=sizeof(key);,所以 key = 20000 + 4 = 20004。问题是你正在尝试 free 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;
}
于 2013-06-27T13:01:02.850 回答
1

只需删除该行:

key+=sizeof(key);

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

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

于 2013-06-27T13:22:29.403 回答
-1

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

这是由于文件指针是全局的,所以每当任何读取器尝试读取并且在 b/w 中,另一个读取器读取并关闭文件指针,因此当另一个未完成读取的读取器尝试在读取后关闭文件指针时。所以发生的事情是文件指针已经关闭它没有指向任何文件。我使用的解决方案。我没有声明文件指针全局,而是将它声明为读取器函数的本地,否则您可以检查文件指针是否为 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);
}
于 2014-04-12T12:37:24.270 回答