Ошибка утверждения отладки! Выражение: _BLOCK_TYPE_IS_VALID

Я получаю это сообщение об ошибке:

Ошибка утверждения отладки!

Выражение:_BLOCK_TYPE_US_VALID(pHead-›nBlockUse)

при попытке сделать следующее

#include <vector>
#include <algorithm>
using namespace std;

class NN
{
public:
    NN(const int numLayers,const int *lSz,const int AFT,const int OAF,const double initWtMag,const int UEW,const double *extInitWt);
    double sse;
    bool operator < (const NN &net) const {return sse < net.sse;}
};

class Pop
{
    int popSize;
    double a;
public:

    Pop(const int numLayers,const int *lSz,const int AFT,const int OAF,const double initWtMag,const int numNets,const double alpha);
    ~Pop();
    vector<NN> nets;
    void GA(...);
};

Pop::Pop(const int numLayers,const int *lSz,const int AFT,const int OAF,
         const double initWtMag,const int numNets,const double alpha)
{
    popSize=numNets;
    a=alpha;
    nets.reserve(popSize);
    for(int i=0;i<popSize;i++)
    {
        NN *net = new NN (numLayers,lSz,AFT,OAF,initWtMag,0,0);
        nets.push_back(*net);
    }
}

void Pop::GA()
{
...
        sort(nets.begin(),nets.end());
...
}

Ошибка, по-видимому, связана с функцией сортировки. Я проверяю все экземпляры вектора сети, и они, кажется, в порядке, имеют разные sse. Самое смешное, что я создал более простой вариант приведенного выше кода (см. ниже), и он работал без каких-либо ошибок. Я разрушаю свой мозг. Пожалуйста помоги.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

class Student
{
public:
    string name;
    double grade;
    Student(string,double);
    bool operator < (const Student &st) const {return grade < st.grade;}
};

Student::Student(string stName,double stGrade)
{
    name = stName;
    grade = stGrade;
}

int main()
{
    vector<Student> group;
    Student *st;
    st = new Student("Bill",3.5);
    group.push_back(*st);
    st = new Student("John",3.9);
    group.push_back(*st);
    st = new Student("Dave",3.1);
    group.push_back(*st);
    sort(group.begin(),group.end());
    for each(Student st in group)
        cout << st.name << " " << st.grade << endl;
    cin.get();
    return(0);
}

person Community    schedule 09.07.2009    source источник
comment
В вашем коде масса утечек памяти. Вы вызываете новый NN, а затем добавляете объект в вектор‹NN› — объект копируется в вектор, а исходный объект остается в куче, и вы его не удаляете. Это утечка памяти, но вряд ли она является причиной проблемы.   -  person sharptooth    schedule 09.07.2009
comment
Отвечает ли это на ваш вопрос? Почему я получаю утверждения _CrtIsValidHeapPointer(block) и/или is_block_type_valid(header-›_block_use)?   -  person ead    schedule 02.11.2020


Ответы (5)


Утверждение _BLOCK_TYPE_IS_VALID запускается, когда вы перезаписываете заголовок блока, выделенного new. Это происходит, когда вы нарезаете объекты, используете мертвые объекты и т. д.

Вы должны взглянуть на свой полный код и попытаться работать с данными, которые есть в вашем отладчике. Этот короткий фрагмент кода содержит несколько «любопытных» примеров использования C++, но не содержит очевидных моментов, в которых это приводит к описанной ошибке (по крайней мере, для меня).

person Christopher    schedule 09.07.2009

из моего опыта. Этот тип ошибки может быть вызван повреждением кучи. поэтому .. вы должны сначала проверить наличие утечек памяти. Если вы используете Visual Studio, используйте _CrtCheckMemory().

person Ujjwal Singh    schedule 12.01.2012

Спасибо всем. Во-первых, я очищаю память, выделенную для вектора сетей внутри деструктора Pop, с помощью

Pop::~Pop()
{
    //nets.clear();
    nets.~vector<NN>();
}

Сообщение об ошибке мало что говорит, и я был бы признателен, если бы кто-нибудь показал мне, как заставить MSVC 2008 показывать более подробную информацию. Вот что там написано (по какой-то причине я не могу вырезать и вставить, поэтому перепечатываю):

Debug assertion failed!
Programm: ... GANN.exe
File: ... dbgedl.cpp
line: 52
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
For information how ...

Когда я нажимаю отладку, компилятор показывает мне строку 52 файла dbgdel.cpp:

_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

внутри

удаление оператора void (void *pUserData)

Вот еще мой код, показывающий, что происходит, прежде чем я попытаюсь отсортировать

double Pop::GA(...)
{
    for (int gen=0;gen<ngen;gen++)
    {
        int istart=0;
        if(gen>0) istart=eliteSize;
        for(int i=istart;i<popSize;i++)
            nets[i].getSSE(in,tgt,ntr,discount);

        for(int i=istart;i<popSize;i++)
        {
            cout << i << " " << nets[i].sse << endl;
        }

        sort(nets.begin(),nets.end());

Все работает правильно до точки sort(). Указатель lSz используется внутри NN для хранения количества узлов в каждом слое нейронной сети, например, lSz[3]={12,5,1} (12 входов, один скрытый слой с 5 нейронами и один выход). Он используется для создания трехмерного массива весов для каждого соединения сети. Каждая сеть NN (а их 100) внутри Population имеет свой массив весов. Но они имеют один и тот же lSz[] и другие структурные параметры, которые, к сожалению, копируются из другого экземпляра NN в другой. Я хотел использовать static для объявления этих общих членов класса, но это предотвратило бы распараллеливание.

person Community    schedule 09.07.2009

Я только что обнаружил, что если я делаю поп-конструкцию вот так

Pop::Pop(const int numLayers,const int *lSz,const int AFT,const int OAF,
         const double initWtMag,const int numNets,const double alpha)
{
    popSize=numNets;
    a=alpha;
    cout << "defined a\n";
    nets.reserve(popSize);
    NN *net = new NN (numLayers,lSz,AFT,OAF,initWtMag,0,0);
    for(int i=0;i<popSize;i++)
    {
        //NN *net = new NN (numLayers,lSz,AFT,OAF,initWtMag,0,0);
        nets.push_back(*net);
    }
}

Тогда все работает, включая sort(). Но это не работает для меня, потому что теперь вектор сетей содержит один и тот же экземпляр NN popSize раз. Идея заключалась в том, чтобы инициализировать каждый из этих экземпляров по отдельности. Каждый экземпляр NN должен иметь свой собственный массив весов, случайным образом инициализируемый внутри конструктора NN:

NN::NN(const int numLayers,const int *lSz,const int AFT,const int OAF,const double initWtMag,
       const int UEW,const double *extInitWt)
{
//  set number of layers and their sizes
    nl=numLayers;
    ls=new int[nl];
    for(int i=0;i<nl;i++) ls[i]=lSz[i];

//  set other parameters
    aft=AFT;
    oaf=OAF;
    binMid=0.0;
    if(aft==0) binMid=0.5;

//  allocate memory for output of each neuron
    out = new double*[nl];
    for(int i=0;i<nl;i++) out[i]=new double[ls[i]];

//  allocate memory for weights (genes)
//  w[lr #][neuron # in this lr][input # = neuron # in prev lr]
    w = new double**[nl];
    for(int i=1;i<nl;i++) w[i]=new double*[ls[i]];
    for(int i=1;i<nl;i++)                   // for each layer except input
        for(int j=0;j<ls[i];j++)            // for each neuron in current layer
            w[i][j]=new double[ls[i-1]+1];  // w[][][ls[]] is bias

//  seed and assign random weights (genes)
    SYSTEMTIME tStart,tCurr;
    GetSystemTime(&tStart);
    for(;;)
    {
        GetSystemTime(&tCurr);
        if(tCurr.wMilliseconds!=tStart.wMilliseconds) break;
    }
    srand(tCurr.wMilliseconds);
    int iw=0;
    for(int i=1;i<nl;i++)                   // for each layer except input
        for(int j=0;j<ls[i];j++)            // for each neuron in current layer
            for(int k=0;k<=ls[i-1];k++)     // for each input of curr neuron incl bias
                if(UEW==0) w[i][j][k]=initWtMag*2.0*(rand()/(double)RAND_MAX-0.5);
                else w[i][j][k]=extInitWt[iw++];
}
person Community    schedule 09.07.2009

Иногда это происходит из-за того, что у вас есть строка длины x, и вы случайно вставили в нее более длинное слово... вот что произошло в моем случае.

person Reuben    schedule 07.09.2012
comment
это должен быть комментарий, а не ответ - person wich; 28.09.2012