*** glibc检测到*** ./a.out:双免费或腐败(外出):0xbfe69600 ***

时间:2014-03-22 04:01:40

标签: c++ debugging free glibc backtrace

我正在做一个程序来代表一个表#34;学生"。它具有属性' 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)

2 个答案:

答案 0 :(得分:13)

  

我收到错误,我不认识

错误只是意味着您已经损坏了堆。

破坏堆的最常见方法是:

  • 写完分配结束
  • 释放你没有分配的记忆
  • 两次释放东西。

发现错误的最快方法是在Valgrind下运行二进制文件。

答案 1 :(得分:3)

首先要修改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个学生,则代码将访问不存在的阵列单元格。因此,将发生访问冲突/程序崩溃/意外行为。

结束编辑一个


开始编辑两个
163的硬编码值可以替换为标题最顶部附近的用户定义的宏,以便对修改学生和/或学生详细信息的最大数量进行简单修改。例如:

#define MAX_STUDENTS 25
#define MAX_COLUMNS 8

然后在标题和cpp中,宏在当前使用163的所有地方使用。然后,循环的构造函数如下所示:

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
}


结束编辑两个


开始编辑三
在创建一个只声明Table1的本地实例的唯一main.cpp后,在for循环体中调用Table1 :: InsertStudent,然后调用Table1 :: Print,以下建议应该有助于改进并希望解决的问题。因此,在观察一起运行的打印输出之后,对Table1构造函数,InsertStudent和Print成员函数的修改如下:

Table1头文件:

#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源码(类实现)。流操纵器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
      }
   }
}

此最新版本应解决已发布的问题。希望这些建议能够促进对iomanip助手的进一步研究,以便只有数据存储在Students数组中。用于确认打印操作的字符串值(例如"students")也可以成为用户定义的宏。

结束编辑三