*** Обнаружен glibc *** ./a.out: двойное освобождение или повреждение (out): 0xbfe69600 ***

Я делаю программу для представления таблицы «Студенты». Он имеет атрибуты «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]<< ")";

}}
}

Мой 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

ОШИБКА заключается в следующем:

    *** 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)

1

Решение

Я получаю ошибку, которую не узнаю

Ошибка просто означает, что вы испортили кучу.

Наиболее распространенные способы повреждения кучи:

  • писать после окончания распределения
  • освобождая память, которую вы не выделяли
  • освобождая что-то дважды.

Самый быстрый способ обнаружить вашу ошибку — запустить бинарный файл под Valgrind.

13

Другие решения

Самым первым делом нужно изменить конструктор 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
}
}

Ниже представлены три уникальных изменения. Пожалуйста, просмотрите их все, чтобы лучше понять ситуацию и возможные пути ее решения.

Начать редактировать один

Table1::InsertStudent(string ID, string FN, string LN) не гарантирует, что RowPos находится в диапазоне 0 <= RowPos < 16, Если будет добавлен 17-й студент, то код получит доступ к несуществующим ячейкам массива. Следовательно, нарушение доступа / сбой программы / неожиданное поведение.

Конец редактировать один

Начать редактировать два
Жестко закодированные значения 16 а также 3 могут быть заменены пользовательскими макросами в самом верху заголовка, чтобы иметь простую модификацию для изменения максимального количества учащихся и / или сведений о них. Например:

#define MAX_STUDENTS 25
#define MAX_COLUMNS 8

Затем в заголовке и в cpp макросы используются во всех местах, где в данный момент используется 16 а также 3, Конструктор для цикла будет выглядеть так:

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

Начать редактировать три

После создания уникального main.cpp, который объявляет только локальный экземпляр Table1, вызывает Table1 :: InsertStudent в теле цикла for, а затем вызывает Table1 :: Print, следующие предложения должны помочь улучшить и, надеюсь, решить проблемы. Итак, после наблюдения за выводом печати, работающей вместе, изменения в конструкторе Table1, функциях InsertStudent и Print следующие:

Заголовочный файл таблицы 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 (реализация класса). Ручной манипулятор setw используется для настройки экрана вывода для отображения столбцов. Настоятельно рекомендуется ознакомиться с более подробной информацией здесь: станд :: setw. Также обратитесь к копии книги Страуструпа. Обратите внимание, что #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
}
}
}

Эта последняя версия должна решить опубликованные проблемы. Надеемся, что предложения будут способствовать дополнительным исследованиям iomanip помощники, так что в массиве Students хранятся только данные. Строковое значение, используемое для подтверждения действия печати (например, "students") также может стать определяемым пользователем макросом.

Конец Править Три

3

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector