2015-02-23 3 views
-1

Я пишу простой ANN (нейронная сеть) для приближения функций. Я получил сообщение с сообщением: «Куча повреждена». Я нашел несколько советов, как их решить, но ничего не помогает. я получил ошибку в первой строке этой функции:C++ куча коррупции на новом

void LU(double** A, double** &L, double** &U, int s){ 
    U = new double*[s]; 
    L = new double*[s]; 
    for (int i = 0; i < s; i++){ 
     U[i] = new double[s]; 
     L[i] = new double[s]; 
     for (int j = 0; j < s; j++) 
      U[i][j] = A[i][j]; 
    } 
    for (int i = 0, j = 0; i < s; i = ++j){ 
     L[i][j] = 1; 
     for (int k = i + 1; k < s - 1; k++){ 
      L[k][j] = U[k][j]/U[i][j]; 
      double* vec_t = mul(U[i], L[k][j], s); 
      for (int z = 0; z < s; z++) 
       U[k][z] = U[k][z] - vec_t[z]; 
      delete[] vec_t; 
     } 
    } 
}; 

Как я понял из информации debagger в: два массива (U и L) был принят для работы с некоторыми адресами в памяти. И это довольно странно, потому что я не инициализировал его. Я вызываю эту функцию два раза, и в первый раз она работает хорошо (нормально, по крайней мере, она работает), но при втором вызове она сработает. Я не знаю, как его решить.
Ссылка на весь проект: CLICK
Я работаю в MS Visual Studio 2013 под Windows 7 x64.

UPDATE
Согласно некоторым комментариям ниже я должен предоставить некоторую аддитивную информацию.
Прежде всего, извините за качество кода. Я написал это только для себя в течение 2 дней.
Во-вторых, когда я сказал «при втором вызове», я имею в виду, что сначала я вызываю LU, когда мне нужно получить определитель S (я использую LU-декомпозицию для этого), и он работает без каких-либо сбоев. Второй вызов - это когда я пытаюсь получить обратную матрицу (то же самое, S). И когда я вызываю detLU в [0, 0] точке матрицы (чтобы получить кофактор), я получил этот крах.
В-третьих, если я правильно получаю информацию от debagger, массивы L и U передают функцию при втором вызове с уже определенными адресами памяти. Я не могу понять, почему, потому что перед вызовом LU я только что написал «double ** L; double ** U;» без какой-либо инициализации.
Я могу попробовать предоставить дополнительную информацию об отладке или некоторые тесты, если кто-нибудь объяснит мне, что именно я должен делать.

+0

Просьба создать [SSCCE] (http://www.sscce.org). –

+0

«но при втором вызове это сбой» может означать много чего. Пожалуйста, будьте конкретны. – thang

+1

Куча могла быть повреждена в любое время, даже вне этой функции или до ее вызова. – molbdnilo

ответ

1

Точка, в которой вы получаете ошибку/сбой при куче, обычно является симптомом фактического переполнения/переполнения кучи или другой ошибки памяти в какой-то другой момент/точку в прошлом. Вот почему повреждение кучи может быть трудно отследить.

У вас есть много кода и все двойные указатели трудно отследить, но я заметил один потенциальный вопрос:

double** initInWeights(double f, int h, int w) { 
    double** W = new double*[h]; 
    for (int i = 0; i < 10; i++) { 
     W[i] = new double[w]; 

Цикл будет переполнение W[] если h меньше 10. Скорее всего, где-то в вашем коде у вас есть переполнение/переполнение буфера или использование памяти после ее освобождения. Сложность и дизайн вашего кода затрудняют точное определение.

Есть ли причина, по которой вы используете необработанные двойные указатели вместо std::vector<std::vector<double>>? Это приведет к удалению всего кода управления ручным управлением памятью, что сделает ваш код короче, проще и, что более важно, устранит проблему кучи.

Запрет на то, что вы должны дважды проверить, что все выделенные вручную ячейки являются правильными, а контуры доступа никогда не могут выйти за пределы.

Update - Я думаю, ваша проблема может лежать переполнение буфера в функции extract() в matrix.cpp:

double** extract(double** mat, int s, int col, int row) 
{ 
    double** ext = new double*[s - 1]; 

    for (int i = 0; i < s - 1; i++) 
    { 
     ext[i] = new double[s - 1]; 
    } 

    int ext_c = 0, ext_r = 0; 

    for (int i = 0; i < s; i++) 
    { 
     if (i != row) 
     { 
      for (int j = 0; j < s; j++) 
      {          // Overflow on ext_c here 
       if (j != col) ext[ext_r][ext_c++] = mat[i][j]; 
      } 
      ext_r++; 
     } 
    } 

    return ext; 
}; 

Вы никогда не сбросить ext_c так просто продолжает увеличиваться в размерах до (s-1)*(s-1), которые, очевидно, переполняет массив ext[].Чтобы это исправить, нужно просто изменить определение внутреннего цикла к:

for (int j = 0, ext_c = 0; j < s; j++) 

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

+0

Да, я получил это. Это так просто ... и глупая ошибка. Большое спасибо! К сожалению, у меня недостаточно репутации, чтобы проголосовать за ваш ответ. В любом случае, благодарю Вас. Теперь у меня будет большая головная боль с тестом и проверка градиентной толерантности, но по крайней мере база проекта работает. –

Смежные вопросы