C++ *** 检测到 glibc *** ./a.out: double free or corruption (out): 0xbfe69600 ***
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22573292/
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 *** ./a.out: double free or corruption (out): 0xbfe69600 ***
提问by user3448739
I'm doing a program to represent a table of "Students". It has the attributes 'ID', 'First Name' and 'Last Name'. I did a two-dimensional array and put cout statements all throughout to check... The correct info IS stored in the correct cell, but I get an error I don't recognize. the code for the .cpp file is:
我正在做一个程序来表示“学生”表。它具有属性“ID”、“名字”和“姓氏”。我做了一个二维数组,并在整个过程中放置了 cout 语句来检查......正确的信息存储在正确的单元格中,但我收到一个我不认识的错误。.cpp 文件的代码是:
#include "Table1.h"
#include <sstream>
#include <iostream>
using namespace std;
Table1::Table1(){
RowPos = 1;
ColPos = 0;
for(int i=1; i<16; i++)
{
for(int j=0; j<3 ; j++)
Students[i][j] = "FakeNull"; // fill the array with Null value
}
}
string Table1::InsertStudent(string ID, string FN, string LN){
Students[0][0] = "StudentID";
Students[0][1] = "FirstName";
Students[0][2] = "LastName";
Students[RowPos][ColPos] = ID; //Assign ID to first column
ColPos++; //Move to next column
Students[RowPos][ColPos] = FN;
ColPos++;
Students[RowPos][ColPos] = LN;
ColPos++;
ColPos = 0;
RowPos++;
}
void Table1::Print(string Name){
if(Name == "students"){
for(int i=1; i<16; i++)
{
int j=0;
if(Students[i][j] == "FakeNull")
break;
else
cout<< "("<< Students[i][j]<< ",";
j++;
cout<< Students[i][j]<< ",";
j++;
cout<< Students[i][j]<< ")";
}
}
}
My Table1.h is:
我的 Table1.h 是:
#include <iostream>
using namespace std;
#include <string>
#ifndef GRADE_HEADER
#define GRADE_HEADER
class Table1
private:
string Students[16][3];
string Grades[16][3];
int RowPos;
int ColPos;
public:
Table1();
string InsertStudent(string, string, string);
string InsertGrade(string, string, string, string);
void Print(string);
void Select(string, string, int);
void Select(string, string, string);
void Select(string, string, char);
void Join();
string Converter(int);
};
#endif
The ERROR is the following:
错误如下:
*** glibc detected *** ./a.out: double free or corruption (out): 0xbfbdeae0 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xeadee2]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0x9a951f]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1b) [0x99099b]
/usr/lib/i386-linux-gnu/libstdc++.so.6(+0x909dc)[0x9909dc]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSsD1Ev+0x2e)[0x990a4e]
./a.out[0x8049299]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xe514d3]
./a.out[0x8048a71]
======= Memory map: ========
003a0000-003ca000 r-xp 00000000 08:01 150255 /lib/i386-linux-gnu/libm-2.15.so
003ca000-003cb000 r--p 00029000 08:01 150255 /lib/i386-linux-gnu/libm-2.15.so
003cb000-003cc000 rw-p 0002a000 08:01 150255 /lib/i386-linux-gnu/libm-2.15.so
005a5000-005a6000 r-xp 00000000 00:00 0 [vdso]
007c5000-007e5000 r-xp 00000000 08:01 150250 /lib/i386-linux-gnu/ld-2.15.so
007e5000-007e6000 r--p 0001f000 08:01 150250 /lib/i386-linux-gnu/ld-2.15.so
007e6000-007e7000 rw-p 00020000 08:01 150250 /lib/i386-linux-gnu/ld-2.15.so
00900000-009d8000 r-xp 00000000 08:01 393409 /usr/lib/i386-linux gnu/libstdc++.so.6.0.16
009d8000-009d9000 ---p 000d8000 08:01 393409 /usr/lib/i386-linux gnu/libstdc++.so.6.0.16
009d9000-009dd000 r--p 000d8000 08:01 393409 /usr/lib/i386-linux gnu/libstdc++.so.6.0.16
009de000-009e5000 rw-p 00000000 00:00 0
00c13000-00c2f000 r-xp 00000000 08:01 132412 /lib/i386-linux-gnu/libgcc_s.so.1
00c2f000-00c30000 r--p 0001b000 08:01 132412 /lib/i386-linux-gnu/libgcc_s.so.1
00c30000-00c31000 rw-p 0001c000 08:01 132412 /lib/i386-linux-gnu/libgcc_s.so.1
00e38000-00fdc000 r-xp 00000000 08:01 150260 /lib/i386-linux-gnu/libc-2.15.so
00fdc000-00fde000 r--p 001a4000 08:01 150260 /lib/i386-linux-gnu/libc-2.15.so
00fde000-00fdf000 rw-p 001a6000 08:01 150260 /lib/i386-linux-gnu/libc-2.15.so
00fdf000-00fe2000 rw-p 00000000 00:00 0
08048000-0804a000 r-xp 00000000 00:19 52698567
0804a000-0804b000 r--p 00001000 00:19 52698567
0804b000-0804c000 rw-p 00002000 00:19 52698567
09df7000-09e18000 rw-p 00000000 00:00 0 [heap]
b77c9000-b77cc000 rw-p 00000000 00:00 0
b77de000-b77e3000 rw-p 00000000 00:00 0
bfbbe000-bfbdf000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)
回答by Employed Russian
I get an error I don't recognize
我收到一个我不认识的错误
The error simply means that you've corrupted heap.
该错误仅表示您已损坏堆。
The most common ways to corrupt heap are:
损坏堆的最常见方法是:
- writing past the end of allocation
- freeing memory that you didn't allocate
- freeing something twice.
- 在分配结束后写入
- 释放你没有分配的内存
- 两次释放某物。
The fastest way to discover your bug is to run your binary under Valgrind.
发现错误的最快方法是在Valgrind下运行二进制文件。
回答by CPlusPlus OOA and D
The very first thing is to modify the Table1 constructor like so:
第一件事是像这样修改 Table1 构造函数:
Table1::Table1()
{
//
// C++ arrays are zero based, previous code skips the 0th row.
// The RowPos and starting value for i are now zero.
//
RowPos = 0;
ColPos = 0;
for(int i=0; i<16; i++)
{
for(int j=0; j<3 ; j++)
Students[i][j] = "FakeNull"; // fill the array with Null value
}
}
There are three unique edits below. Please review all of them to better understand the situation and possible ways to solve it.
下面是三个独特的编辑。请查看所有这些内容以更好地了解情况和可能的解决方法。
Start Edit One
开始编辑一
The Table1::InsertStudent(string ID, string FN, string LN)
does not make sure that RowPos is in the range of 0 <= RowPos < 16
. If the 17th student is added, then the code will access array cells that do not exist. Hence an access violation / program crash / unexpected behavior will occur.
在Table1::InsertStudent(string ID, string FN, string LN)
不确保RowPos是在范围内0 <= RowPos < 16
。如果添加了第 17 个学生,则代码将访问不存在的数组单元格。因此会发生访问冲突/程序崩溃/意外行为。
End Edit One
结束编辑一
Start Edit Two
The hard coded values of 16
and 3
can be replaced with user defined macros near the very top of the header, to have a simple modification for modifying the maximum number of students and/or student details. For example:
开始编辑两个
硬编码的值16
,并3
可以与附近的头的最顶端用户定义的宏所取代,有修改学生和/或学生的详细信息的最大数量的简单修改。例如:
#define MAX_STUDENTS 25
#define MAX_COLUMNS 8
Then later in the header and the cpp, the macros are used in all places currently using 16
and 3
. The constructor for loop would then look like:
然后在标题和 cpp 中,宏用于当前使用16
和的所有地方3
。for 循环的构造函数将如下所示:
for(int i=0; i<MAX_STUDENTS; i++)
{
for(int j=0; j<MAX_COLUMNS ; j++)
Students[i][j] = "FakeNull"; // fill the array with Null value
}
End Edit Two
结束编辑二
Start Edit Three
After creating a unique main.cpp that only declares a local instance of Table1, calls Table1::InsertStudent in a for loop body, and then calls Table1::Print, the following suggestions should help to improve and hopefully resolve the issues. So, after observing the printed output running together, modifications to the Table1 constructor, InsertStudent and Print member functions are the following:
开始编辑三
创建唯一的只声明Table1本地实例的main.cpp,在for循环体中调用Table1::InsertStudent,然后调用Table1::Print后,以下建议应该有助于改进并希望解决问题. 所以,在观察一起运行的打印输出后,对 Table1 构造函数、InsertStudent 和 Print 成员函数的修改如下:
Table1 header file:
表1头文件:
#ifndef GRADE_HEADER
#define GRADE_HEADER
//
// The first two lines are not necessary and should be deleted
// Note that "std::" must be used in front of the string class
//
// #include <iostream>
// using namespace std;
#include <string>
//
// Added three user defined macros to make modifications easy and to
// to have a single location for the signaling string value to stop
// printing student details to the cout stream.
//
#define MAX_STUDENTS 16
#define MAX_COLUMNS 3
#define EMPTY_CELL "FakeNull"
class Table1
{ // added
private:
std::string Students[MAX_STUDENTS][MAX_COLUMNS];
std::string Grades[MAX_STUDENTS][MAX_COLUMNS];
int RowPos;
int ColPos;
public:
Table1();
std::string InsertStudent(std::string ID, std::string FN, std::string LN);
void Print(std::string Name);
std::string InsertGrade(std::string, std::string, std::string, std::string);
void Select(std::string, std::string, int);
void Select(std::string, std::string, std::string);
void Select(std::string, std::string, char);
void Join();
std::string Converter(int);
};
#endif
Table1 cpp source (class implementation). The stream manipulator setw
is used to configure the output screen to display the columns. It is highly recommended to review more details here: std::setw. Also consult a copy of the Stroustrup book. Note that the #include <iomanip>
is absolutely necessary to define an output width. The commas and parenthesis in the body of the Print method are gone. Any presentation style is possible, the Print method modifications are a sample, indicating one way to do it. Many others ways are possible. Note that this modification set no longer has any fixed value strings assigned to the zeroth position. All student data commences at index zero and is valid up to and including the MAX_STUDENTS - 1
index position.
表 1 cpp 源代码(类实现)。流操纵setw
器用于配置输出屏幕以显示列。强烈建议在此处查看更多详细信息:std::setw。另请参阅 Stroustrup 书的副本。请注意,#include <iomanip>
定义输出宽度是绝对必要的。Print 方法主体中的逗号和括号已消失。任何演示风格都是可能的,Print 方法修改是一个示例,表明了一种方法。许多其他方式也是可能的。请注意,此修改集不再具有分配给第零个位置的任何固定值字符串。所有学生数据从索引零开始,直到MAX_STUDENTS - 1
索引位置(包括索引位置)都是有效的。
#include "Table1.h"
#include <sstream>
#include <iostream>
#include <iomanip>
using namespace std;
Table1::Table1()
{
//
// C++ arrays are zero based, previous code skips the 0th row.
// The RowPos and starting value for i are now zero.
//
RowPos = 0;
ColPos = 0;
//
// Initialize the MAX_STUDENTS elements to a set string, indicating
// no data present. The use of the zeroth element as string constants
// is no longer necessary.
//
for(int i=0; i < MAX_STUDENTS; i++)
{
for(int j=0; j < MAX_COLUMNS; j++)
Students[i][j] = EMPTY_CELL; // fill the array with Null value
}
}
//
// Note that sOut is an additional local variable to provide a string output
// for success or failure. The range checking is new too.
//
string Table1::InsertStudent(string ID, string FN, string LN)
{
string sOut = "Successfully added student";
//
// Must be sure the RowPos index is never beyond the last element of the
// Students array!!!
//
if (RowPos < 0 || RowPos >= MAX_STUDENTS)
{
sOut = "Students array full. Cannot add any more students";
return sOut;
}
Students[RowPos][ColPos] = ID; //Assign ID to first column
ColPos++; //Move to next column
Students[RowPos][ColPos] = FN;
ColPos++;
Students[RowPos][ColPos] = LN;
//
// Incrementing this accomplishes nothing since it is set to zero next
//
// ColPos++;
ColPos = 0;
RowPos++;
return sOut;
}
void Table1::Print(string Name)
{
if(Name == "students")
{
cout << "StudentID" << setw(15) << "FirstName" << setw(17);
cout << "LastName" << endl;
//
// It is much more efficient to declare variables outside a loop and
// not within a loop body. To promote best practices, both variables
// are declared together. The reality is that j is the one which
// should be declared outside the for loop body (or at the same time
// as this: for (int i = 0, j; ...
// Keep in mind that j always has to be set to zero to start the loop body
//
int i, j;
for(i=0; i < MAX_STUDENTS; i++)
{
j=0;
if(Students[i][j] == EMPTY_CELL)
break;
else
{ // added
cout << setw(9) << Students[i][j] << setw(15);
j++;
cout << Students[i][j] << setw(18);
j++;
cout << Students[i][j] << endl;
} // added
}
}
}
This last version should resolve the posted issues. Hopefully the suggestions will foster additional research into the iomanip
helpers so that only data is stored in the Students array. The string value used to confirm the print action (e.g. "students"
) could also become a user defined macro.
最后一个版本应该可以解决发布的问题。希望这些建议将促进对iomanip
helper 的更多研究,以便仅将数据存储在 Students 数组中。用于确认打印操作(例如"students"
)的字符串值也可以成为用户定义的宏。
End Edit Three
结束编辑三