Получение glibc обнаруженной ошибки при попытке удалить части матрицы в C ++ - PullRequest
0 голосов
/ 10 февраля 2011

Когда я запускаю следующий код, я получаю ошибку, обнаруженную с помощью glibc, когда пытаюсь использовать команду delete [] I [i] (всегда при последнем прогоне цикла). Прямо перед циклом, который пытается удалить I [i], я распечатываю значения в последнем ряду I, и он отображается точно так, как и должно, поэтому я не думаю, что проблема связана с циклом быть слишком большим. Что я делаю неправильно? (Я включил каждую строку кода, где ** я показываю).

РЕДАКТИРОВАТЬ 2: сообщение об ошибке полностью:

*** glibc detected *** getParams: free(): invalid next size (fast): 0x086861f0 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x271591]
/lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0x272de8]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x275ecd]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x1cb741]
/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0x1cb79d]
getParams[0x804ac78]
getParams[0x8048943]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x21cbd6]
getParams[0x8048731]
======= Memory map: ========
00110000-001f9000 r-xp 00000000 08:01 396979     /usr/lib/libstdc++.so.6.0.13
001f9000-001fa000 ---p 000e9000 08:01 396979     /usr/lib/libstdc++.so.6.0.13
001fa000-001fe000 r--p 000e9000 08:01 396979     /usr/lib/libstdc++.so.6.0.13
001fe000-001ff000 rw-p 000ed000 08:01 396979     /usr/lib/libstdc++.so.6.0.13
001ff000-00206000 rw-p 00000000 00:00 0 
00206000-00359000 r-xp 00000000 08:01 11272305   /lib/tls/i686/cmov/libc-2.11.1.so
00359000-0035a000 ---p 00153000 08:01 11272305   /lib/tls/i686/cmov/libc-2.11.1.so
0035a000-0035c000 r--p 00153000 08:01 11272305   /lib/tls/i686/cmov/libc-2.11.1.so
0035c000-0035d000 rw-p 00155000 08:01 11272305   /lib/tls/i686/cmov/libc-2.11.1.so
0035d000-00360000 rw-p 00000000 00:00 0 
0074f000-00773000 r-xp 00000000 08:01 11272350   /lib/tls/i686/cmov/libm-2.11.1.so
00773000-00774000 r--p 00023000 08:01 11272350   /lib/tls/i686/cmov/libm-2.11.1.so
00774000-00775000 rw-p 00024000 08:01 11272350   /lib/tls/i686/cmov/libm-2.11.1.so
00a7b000-00a7c000 r-xp 00000000 00:00 0          [vdso]
00d1c000-00d37000 r-xp 00000000 08:01 11276409   /lib/ld-2.11.1.so
00d37000-00d38000 r--p 0001a000 08:01 11276409   /lib/ld-2.11.1.so
00d38000-00d39000 rw-p 0001b000 08:01 11276409   /lib/ld-2.11.1.so
00ec8000-00ee5000 r-xp 00000000 08:01 11272275   /lib/libgcc_s.so.1
00ee5000-00ee6000 r--p 0001c000 08:01 11272275   /lib/libgcc_s.so.1
00ee6000-00ee7000 rw-p 0001d000 08:01 11272275   /lib/libgcc_s.so.1
08048000-0804c000 r-xp 00000000 08:01 4720134    /home/rkappiyo/Dropbox/xingResearch/finalMatlab/getParams
0804c000-0804d000 r--p 00003000 08:01 4720134    /home/rkappiyo/Dropbox/xingResearch/finalMatlab/getParams
0804d000-0804e000 rw-p 00004000 08:01 4720134    /home/rkappiyo/Dropbox/xingResearch/finalMatlab/getParams
08686000-086a7000 rw-p 00000000 00:00 0          [heap]
b7600000-b7621000 rw-p 00000000 00:00 0 
b7621000-b7700000 ---p 00000000 00:00 0 
b774f000-b7751000 rw-p 00000000 00:00 0 
b7762000-b7765000 rw-p 00000000 00:00 0 
bfcd4000-bfce9000 rw-p 00000000 00:00 0          [stack]
Aborted

РЕДАКТИРОВАТЬ: я изменил его, чтобы включить весь код.

void invertMatrix(double **mat, int size) {
//index variables used for looping
int i, j, k;

//L and U are the LU decomposition of mat
double **L, **U;

//invMat is the inverted matrix, which will be stored in mat
double **invMat;

//I is the identity matrix
double **I;

L = new double *[size]; //allocation 1

for(i = 0; i < size; i++)
    L[i] = new double[size]; //allocation 2

U = new double *[size]; //allocation 3

for(i = 0; i < size; i++)
    U[i] = new double[size]; //allocation 4

//compute the LU decomposition of mat and store in L and U
LUDecomp(mat, size, L, U);

invMat = new double *[size]; //allocation 5

for(i = 0; i < size; i++)
    invMat[i] = new double [size]; //allocation 6

I = new double *[size]; //allocation 7

for(i = 0; i < size; i++) {
    I[i] = new double [size]; //allocation 8

    for(j = 0; j < size; j++) {
        if(i == j)
            I[i][j] = 1;
        else
            I[i][j] = 0;
    }
}

for(i = 0; i < size; i++) {
    invMat[i][0] = I[i][0] / L[0][0];

    for(j = 1; j < size; j++) {
        invMat[i][j] = I[i][j];

        for(k = 0; k < j; k++)
            invMat[i][j] -= L[j][k] * invMat[i][k];

        invMat[i][j] /= L[j][j];
    }
}

for(i = 0; i < size; i++) {
    mat[i][size - 1] = invMat[i][size - 1] / U[size - 1][size - 1];

    for(j = size - 2; j > -1; j--) {
        mat[i][j] = invMat[i][j];

        for(k = j + 1; k < size; k++)
            mat[i][j] -= U[j][k] * mat[i][k];

        mat[i][j] /= U[j][j];
    }
}

for(i = 0; i < size; i++) {
    delete[] L[i]; //free allocation 2
    delete[] U[i]; //free allocation 4
    delete[] invMat[i]; //free allocation 6
    delete[] I[i]; //free allocation 8
}

delete[] L; //free allocation 1
delete[] U; //free allocation 3
delete[] invMat; //free allocation 5
delete[] I; //free allocation 7
}

1 Ответ

1 голос
/ 14 марта 2011

Меня действительно раздражает такой способ выделения двумерных матриц, поэтому я написал простую процедуру C для выделения и инициализации двумерного массива одним вызовом malloc (), чтобы вы могли освободить память с помощью одного свободного () вызов. (Обратите внимание, что это может быть расширено / изменено для использования нового символа [...])

/* set up the memory for a 2D matrix with entries of size "size" */
void** matrix2D(long rows, long columns, long size)
{
    long    i;
    unsigned long long      row_size = (unsigned long long)columns * (unsigned long long)size;
    unsigned long long      data_size = ((unsigned long long)rows * (unsigned long long)columns + 1) * (unsigned long long)size;
    unsigned long long      pointer_size = (unsigned long long)rows * sizeof(void*);
    void**  result;

    if ( (result = (void**)malloc((size_t)(data_size + pointer_size))) == NULL ) {
            return NULL;
    }

    // take the first bit for a vector pointing to the m_pData for each row
    char* pdata = (char*)result + pointer_size;
    if ((unsigned long)pdata % size) {
      pdata += size - (unsigned long)pdata % size;
    }

    // for each row, set up the pointer to its m_pData
    for (i = 0; i < rows; i++) {
            result[i] = (void*)pdata;
            pdata += row_size;
    }

    return result;
}

Тогда вы можете создать каждую из ваших матриц, используя одну строку, например ::

double** I = (double**)matrix2D(size, size, sizeof(double));

и они могут быть освобождены с помощью, например ,::1007*

free(I);

Гораздо проще. Кроме того, тогда значения данных матрицы являются смежными, поэтому, например, если вы создаете массив целых чисел и хотите инициализировать их все в ноль, вы можете сделать:

int** array = (int**)matrix2D(height, width, sizeof(int));
memset(array, 0, height * width * sizeof(int));

или, чтобы инициализировать его заданным (ненулевым) значением:

for (int i = 0; i < height * width; ++i)
    array[i] = value;
...