C++ 检测到 glibc:双重释放或损坏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17343832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
glibc detected : double free or corruption
提问by ybc
I will explain the brief coding steps I have done and area where I am facing the problem
我将解释我所做的简短编码步骤以及我面临问题的区域
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;
}
when tried compiling and running the above code, I am able to successfully compile the code but got "glibc detected : double free or corruption" when tried running the application.
尝试编译和运行上述代码时,我能够成功编译代码,但在尝试运行应用程序时检测到“glibc 检测到:双重释放或损坏”。
Now my question is I created a char pointer(char *key =(char*)malloc(sizeof(char) * 25);
)
and successfully assigned memory to it using malloc. After completing my process when I tried freeing of that char pointer I am getting double free or corruption error. I learned that any variable assigned memory with malloc/calloc should be freed finally. Please tell why I am this getting error, why I should not do this? Please tell me how the memory operations are ongoing on char* key
(if possible pictorially).
现在我的问题是我创建了一个字符指针(char *key =(char*)malloc(sizeof(char) * 25);
)并使用 malloc 成功为其分配了内存。当我尝试释放那个字符指针时完成我的过程后,我得到了双重释放或损坏错误。我了解到任何使用 malloc/calloc 分配的内存的变量最终都应该被释放。请告诉我为什么会出现这个错误,为什么我不应该这样做?请告诉我内存操作是如何进行的char* key
(如果可能的话)。
Note: The code presented above is not the complete code, I just explained where I am getting the problem and if I am not freeing the pointer variable, my application is running successfully.
注意:上面提供的代码不是完整的代码,我只是解释了我在哪里遇到问题,如果我没有释放指针变量,我的应用程序运行成功。
回答by RichieHindle
By doing this:
通过做这个:
key+=sizeof(key);
your key
variable is no longer pointing to the start of the memory you allocated. You must pass the original pointer to free()
. You need to store the original pointer in another variable so that you can correctly free()
it at the end.
您的key
变量不再指向您分配的内存的开头。您必须将原始指针传递给free()
. 您需要将原始指针存储在另一个变量中,以便您可以free()
在最后正确使用它。
(You may be able to simply remove that line - I'm not sure what it's doing, given that sizeof(key)
is either 4 or 8. I suspect it's redundant.)
(您可以简单地删除该行 - 我不确定它在做什么,因为它sizeof(key)
是 4 或 8。我怀疑它是多余的。)
回答by nouney
That's because of this line : key+=sizeof(key);
. key
doen't contain the same address as the malloc
returned address.
那是因为这一行 : key+=sizeof(key);
。key
不包含与malloc
返回地址相同的地址。
For example:
例如:
char *key =(char*)malloc(sizeof(char) * 25);
char *key =(char*)malloc(sizeof(char) * 25);
Let's say malloc returns the address 20000
(totally dumb address, it's just for the example).
假设 malloc 返回地址20000
(完全愚蠢的地址,仅用于示例)。
Now you're doing key+=sizeof(key);
, so key = 20000 + 4 = 20004. The problem is you're trying to free key
, which points to the address 20004 instead of 20000.
现在你正在做key+=sizeof(key);
,所以 key = 20000 + 4 = 20004。问题是你试图释放key
,它指向地址 20004 而不是 20000。
In order to fix that, try this:
为了解决这个问题,试试这个:
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;
}
回答by Barmar
Simply remove the line:
只需删除该行:
key+=sizeof(key);
key
is not a pointer to an array of strings, it's a pointer to a single string. Every time you increment this, you're reducing the available space in the string. The first time you read a key, there's 25 bytes available. The next time, you've incremented key
by 4 or 8 bytes, but the end of the allocated space hasn't changed, so now there's only 21 or 17 bytes available. The third time it's only 17 or 9 bytes, and so on. After a few iterations, you'll increment key
past the end of the memory block that you allocated, and it will start writing into unallocated memory (or memory that's assigned to other data structures). This is undefined behavior, and will most likely cause unpredictable failures in your program.
key
不是指向字符串数组的指针,而是指向单个字符串的指针。每次增加它时,都会减少字符串中的可用空间。第一次读取密钥时,有 25 个字节可用。下一次,您增加key
了 4 或 8 个字节,但分配空间的末尾没有改变,所以现在只有 21 或 17 个字节可用。第三次它只有 17 或 9 个字节,依此类推。几次迭代后,您将递增key
超过您分配的内存块的末尾,它将开始写入未分配的内存(或分配给其他数据结构的内存)。这是未定义的行为,很可能会导致您的程序出现不可预测的故障。
Since you're using C++, you should use std::string
instead of char[]
for strings, and std::vector
instead of ordinary arrays. These data structures automatically expand as needed, so you avoid buffer overflows like this.
由于您使用的是 C++,您应该使用std::string
而不是char[]
字符串,而std::vector
不是普通数组。这些数据结构会根据需要自动扩展,因此您可以避免像这样的缓冲区溢出。
回答by Kevytosh
this is not taking your code into consideration, but i had a same problem in Reader writer problem (operating systems) http://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem.
这并未考虑您的代码,但我在 Reader writer 问题(操作系统)http://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem 中遇到了同样的问题。
It was due to file pointer being global so whenever any reader tried to read and in b/w another read reads and closes file pointer so when another reader which has not finished reading tried to close file pointer after reading. so what happened is file pointer was already closed it wasn't pointing to any file. Solution i used. Instead of declaring file pointer global i declared it local to reader function that it or else you can check file pointer for NULL and if NULL then don't close the file pointer.
这是由于文件指针是全局的,所以每当任何读者尝试读取时,在黑白中,另一个读取读取并关闭文件指针,因此当另一个尚未完成读取的读取器尝试在读取后关闭文件指针时。所以发生的事情是文件指针已经关闭它没有指向任何文件。我使用的解决方案。我没有将文件指针声明为全局,而是将其声明为读取器函数的本地,否则您可以检查文件指针是否为 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);
}