Malloc ошибка освобождения памяти - C (СИ)
Формулировка задачи:
ЧЯДНТ? Косяк такой:
heap corruption detected before normal block (№0) at 0x...
CRT detected that the application wrote to memory before start of heap buffer.
Листинг программы
- double SizeArr = 5, wData = 8, **Arr0, *Arr1, *Arr2;
- Len = SizeArr * sizeof(double);
- Arr0 = (double**)malloc(SizeArr * sizeof(*Arr0));
- for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)malloc(Len);
- Arr1 = (double*)malloc(Len);
- Arr2 = (double*)malloc(Len);
- for (i = 0; i < SizeArr; ++i)
- Arr[i] = (double*)realloc(Arr[i], wData * sizeof(*Arr));
- free(Arr1); Arr1 = NULL; // нет ошбки
- free(Arr2); Arr2 = NULL; // ошибка
- for (i = 0; i < SizeArr; ++i)
- free(Arr0[i]); // ошибка - срабатывание точки останова
- free(Arr0); Arr0 = NULL;
Код целиком
Листинг программы
- #include <math.h>
- #include <stdio.h>
- #include <iostream>
- #include <ctime>
- void mxmt(double **Data, double **Arr, size_t wData, size_t SizeArr);
- void tred2(double **Arr, size_t SizeArr, double *D0, double *D1);
- void tqli1(double **Arr, size_t SizeArr, double *D0, double *D1, size_t *MaxIter);
- void bevm(double **Arr, size_t SizeArr, double *D0, double *D1, double **DT);
- void ivm(double **DT, double *D0, size_t SizeArr);
- void vxb(double *A, double **B, double **C, size_t whM, size_t wB);
- void smdd(double **C, double *D0, size_t SizeArr);
- void axb(double **A, double **B, double **C, size_t hA, size_t whM, size_t wB);
- void output1(double *D, size_t SizeArr);
- void output2i(double **Arr, size_t SizeArr);
- void output2t(double **Arr, size_t SizeArr);
- void output2r(double **Arr, size_t SizeArr, size_t wData);
- void output2rt(double **Arr, size_t SizeArr, size_t wData);
- int main() {
- setlocale(0, "ru-ru"); srand((size_t)time(0));
- double **Data, **Arr, **DT, *D0, *D1, **SU;
- size_t i, SizeArr = 5, wData = 8, Len, *MaxIter = &i;
- Len = wData * sizeof(**Data);
- Data = (double**)malloc(SizeArr * sizeof(*Data));
- for (i = 0; i < SizeArr; ++i) Data[i] = (double*)malloc(Len);
- for (i = 0; i < SizeArr; ++i)
- for (size_t j = 0; j < wData; ++j) Data[i][j] = 5 - rand() % 11;
- Len = SizeArr * sizeof(double);
- Arr = (double**)malloc(SizeArr * sizeof(*Arr));
- for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)malloc(Len);
- mxmt(Data, Arr, wData, SizeArr);
- puts("Исходные данные (Data): "); output2r(Data, SizeArr, wData);
- puts("Исходная левая симметричная матрица (Data x Data^T): "); output2i(Arr, SizeArr);
- D0 = (double*)malloc(Len); //memset(&D0[0], 0, Len);
- D1 = (double*)malloc(Len); //memset(&D1[0], 0, Len);
- DT = (double**)malloc(3 * sizeof(**DT));
- for (i = 0; i < 3; i++) DT[i] = (double*)malloc(Len);
- tred2(Arr, SizeArr, D0, D1);
- for (i = 0; i < SizeArr; ++i) { DT[0][i] = D0[i]; DT[1][i] = D1[i]; }
- i = 30; tqli1(Arr, SizeArr, D0, D1, MaxIter);
- for (i = 0; i < SizeArr; ++i) DT[2][i] = D0[i];
- puts("Собственные значения (L): "); output1(D0, SizeArr);
- bevm(Arr, SizeArr, D0, D1, DT);
- puts("Собственные векторы (V): "); output2t(Arr, SizeArr);
- ivm(DT, D0, SizeArr);
- puts("Обратный вектор сингулярных значений (S'): "); output1(D0, SizeArr);
- // Arr = D0 x Arr x Data [ V^(T) = (S^(T))^(-1) x U^(T) x A ]
- SU = (double**)malloc(SizeArr * sizeof(**SU));
- for (i = 0; i < SizeArr; i++) SU[i] = (double*)malloc(Len);
- // используем формулу умножения вектора на не транспонированную матрицу,
- // поскольку её содежимое уже транспонировано
- vxb(D0, Arr, SU, SizeArr, SizeArr); //output2t(SU, SizeArr);
- smdd(SU, D0, SizeArr); //output2t(SU, SizeArr);
- for (i = 0; i < SizeArr; ++i)
- Arr[i] = (double*)realloc(Arr[i], wData * sizeof(*Arr));
- axb(SU, Data, Arr, SizeArr, SizeArr, wData);
- puts("Матрица векторов (V), нулевые вектора опущены: "); output2rt(Arr, wData, SizeArr);
- system("pause");
- for (i = 0; i < SizeArr; ++i) free(Data[i]); free(Data); Data = NULL;
- for (i = 0; i < SizeArr; ++i) free(SU[i]); free(SU); SU = NULL;
- for (i = 0; i < 3; ++i) free(DT[i]); free(DT); DT = NULL;
- free(D0); D0 = NULL;
- //free(D1); //D1 = NULL;
- for (i = 0; i < SizeArr; ++i)
- free(Arr[i]);
- //free(Arr); Arr = NULL;
- return 0;
- }
- void mxmt(double **Data, double **Arr, size_t wData, size_t SizeArr) {
- for (size_t i = 0; i < SizeArr; ++i)
- for (size_t j = i; j < SizeArr; ++j) {
- Arr[j][i] = 0.;
- for (size_t k = 0; k < wData; ++k)
- Arr[j][i] += Data[i][k] * Data[j][k];
- Arr[i][j] = Arr[j][i];
- }
- }
- void tred2(double **Arr, size_t SizeArr, double *D0, double *D1) {
- size_t i, j, k, l; double Scale, Sum, Pre, HH;
- /* получение ортогональной матрицы трансформации */
- /* проход по стадиям/итерациям процесса редукции */
- for (i = SizeArr - 1; i > 0; --i) {
- l = i - 1; D0[i] = Scale = 0.;
- /* вычислить сумму модулей строки под главной диагональю */
- for (j = 0; j < i; ++j) Scale += fabs(Arr[i][j]);
- /* сложный процесс везде, кроме последней стадии/итерациям, весь
- обрабатываемый диапазон находится под главной диагональю матрицы */
- if (i < 2 || !Scale) D1[i] = Arr[i][l];
- else { /* преобразование матрицы */
- /* масштабируем строку */
- for (j = 0; j < i; ++j) Arr[i][j] /= Scale;
- /* вычислить сумму квадратов строки */
- for (j = 0; j < i; ++j) D0[i] += Arr[i][j] * Arr[i][j];
- /* работаем с вектором U */
- D1[i] = (Arr[i][l] < 0. ? sqrt(D0[i]) : -sqrt(D0[i]));
- D0[i] -= Arr[i][l] * D1[i]; Arr[i][l] -= D1[i];
- D1[i] *= Scale;
- /* вычисляем предварительный коэффициент Pre */
- for (Pre = 0., j = 0; j < i; ++j) {
- Arr[j][i] = Arr[i][j] / D0[i];
- for (Sum = 0., k = 0; k <= j; ++k) Sum += Arr[j][k] * Arr[i][k];
- for (k = j + 1; k < i; ++k) Sum += Arr[k][j] * Arr[i][k];
- D1[j] = Sum / D0[i]; Pre += Arr[i][j] * D1[j];
- }
- /* трансформируем матрицу */
- HH = Pre / (D0[i] + D0[i]);
- for (j = 0; j < i; ++j) {
- D1[j] -= HH * Arr[i][j];
- for (k = 0; k <= j; ++k)
- Arr[j][k] -= (D1[k] * Arr[i][j] + D1[j] * Arr[i][k]);
- }
- }
- }
- /* сохраняем главную диагональ */
- for (D1[0] = 0., i = 0; i < SizeArr; ++i) D0[i] = Arr[i][i]; /**/
- }
- void tqli1(double **Arr, size_t SizeArr, double *D0, double *D1, size_t *MaxIter) {
- size_t i, j, k, Iter; double b, c, DD, f, g, p, r, s;
- /* сдвигаем массив влево для удобства */
- for (i = 1; i < SizeArr; ++i) D1[i - 1] = D1[i]; D1[i - 1] = 0.;
- for (i = 0; i < SizeArr; ++i) {
- Iter = *MaxIter;
- do { /* диагонализируем миноры с текущей строки */
- /* находим малый поддиагональный элемент для расщепления */
- for (j = i; j < SizeArr - 1; ++j) {
- DD = fabs(D0[j]) + fabs(D0[j + 1]);
- if ((double)(fabs(D1[j] + DD)) == DD) break;
- }
- /* если верхний левый угол минора еще не диагональный */
- if (j != i) {
- /* формирование сдвига */
- g = (D0[i + 1] - D0[i]) / (2. * D1[i]); r = hypot(1., g);
- /* находим сумму модулей d_m и k_s с сохранением исходного знака */
- g += (g >= 0. ? fabs(r) : -fabs(r)); g = D0[j] - D0[i] + D1[i] / g;
- /* плоская ротация оригинального QL алгоритма, сопровождаемая
- ротациями Гивенса для восстановления трехдиагональной формы */
- for (s = c = 1., p = 0., k = j - 1; k < j && k >= i; --k) {
- f = s * D1[k]; b = c * D1[k]; D1[k + 1] = r = hypot(f, g);
- if (r == 0.) { D0[k + 1] -= p; D1[j] = 0.; break; }
- /* основные действия на ротации */
- s = f / r; c = g / r; g = D0[k + 1] - p;
- r = (D0[k] - g) * s + 2. * c * b;
- p = s * r; D0[k + 1] = g + p; g = c * r - b;
- }
- /* безусловный переход к новой итерации при нулевом знаменателе
- и недоведенной до конца последовательности ротаций */
- if (r == 0. && k < j && k >= i) continue;
- /* сохраняем новые значения диагоналей */
- D0[i] -= p; D1[i] = g; D1[j] = 0.;
- }
- } while (j != i && --Iter);
- if (!Iter) { printf("Привышен заданный порог итераций на цикле %d \n", i); break; }
- }
- }
- void bevm(double **Arr, size_t SizeArr, double *D0, double *D1, double **DT) {
- double Div, Delta; size_t i, j, k, l, Rang;
- // цикл поиска сбственных векторов для каждого собственого значения
- for (i = 0; i < SizeArr; ++i) {
- // получаем главную и прилигающие к ней диагонали
- for (j = 0; j < SizeArr; ++j) { D0[j] = DT[0][j] - DT[2][i]; D1[j - 1] = DT[1][j]; }
- // получаем триугольную/трапциидальную матрицу из трёхдиагональной
- Div = 1.; Rang = l = SizeArr - 1; D1[l] = D1[0];
- for (j = 0, k = 1; k < l; ++j, ++k) {
- D0[k] = (D0[j] * D0[k] - D1[l] * D1[j]) / Div;
- D1[l] = D1[k]; D1[k] = D0[j] / Div * D1[k]; Div = D0[j];
- }
- // подсчитываем среднюю линейную погрешность с некоторым запасом
- // кого это не устраивает - считает погрешность как положено
- D0[k] = (D0[j] * D0[k] - D1[l] * D1[j]) / Div;
- Delta = 1.00059 * D0[k]; Div = D0[k] / k; D0[k] = 1.;
- // поиск свободных значений / подсчёт ранга матрицы
- for (j = SizeArr - 2; j; --j, Delta -= Div)
- if (fabs(D0[j]) < Delta && fabs(D1[j]) < Delta) { D0[j] = 1.; --Rang; }
- else break;
- // получаем собственный вектор для текущего собственного значения
- for (j = Rang - 1, k = Rang; j < Rang; --j, --k) D0[j] = -D0[k] / D0[j] * D1[j];
- // нормализуем вектор
- Div = 0.; for (j = 0; j < SizeArr; ++j) Div += D0[j] * D0[j];
- Div = sqrt(Div); for (j = 0; j < SizeArr; ++j) D0[j] /= Div;
- // сохраняем результат в массив векторов в транспонированном виде (по строкам)
- for (j = 0; j < SizeArr; ++j) Arr[i][j] = D0[j];
- }
- }
- void ivm(double **DT, double *D0, size_t SizeArr) {
- size_t i; // подсчитываем сингулярные значения
- for (i = 0; i < SizeArr; ++i) D0[i] = (DT[2][i] > 0 ? sqrt(DT[2][i]) : 0);
- // находим обратную вектор матрицу
- for (i = 0; i < SizeArr; ++i) D0[i] = 1. / D0[i];
- }
- void vxb(double *V, double **B, double **C, size_t whM, size_t wB) {
- size_t i, j;
- for (i = 0; i < whM; ++i) for (j = 0; j < wB; ++j) C[i][j] = V[i] * B[i][j];
- }
- void smdd(double **C, double *D0, size_t SizeArr) {
- // сортировка строк матрицы по убыванию значений вектор матрицы
- size_t Pos = 0, i, j; double Max, Swp, *pSwp;
- for (i = 0; i < SizeArr - 1; ++i) {
- for (j = i + 1, Max = D0[i]; j < SizeArr; ++j)
- if (Max < D0[j]) Max = D0[j], Pos = j;
- if (i != Pos) {
- Swp = D0[i]; D0[i] = D0[Pos]; D0[Pos] = Swp;
- pSwp = C[i]; C[i] = C[Pos]; C[Pos] = pSwp;
- }
- }
- }
- void axb(double **A, double **B, double **C, size_t hA, size_t whM, size_t wB) {
- for (size_t i = 0; i < hA; ++i)
- for (size_t j = 0; j < wB; ++j) {
- C[i][j] = 0.;
- for (size_t k = 0; k < whM; ++k) C[i][j] += A[i][k] * B[k][j];
- }
- }
- void output1(double *a, size_t n) {
- for (size_t x = 0; x < n; ++x) printf("%14.10lf ", a[x]); puts("\n");
- }
- void output2i(double **a, size_t n) {
- for (size_t y = 0; y < n; ++y) {
- for (size_t x = 0; x < n; ++x) printf("%5.0lf ", a[y][x]); puts("");
- } puts("");
- }
- void output2t(double **a, size_t n) {
- for (size_t y = 0; y < n; ++y) {
- for (size_t x = 0; x < n; ++x) printf("%14.10lf ", a[x][y]); puts("");
- } puts("");
- }
- void output2r(double **a, size_t n, size_t m) {
- for (size_t y = 0; y < n; ++y) {
- for (size_t x = 0; x < m; ++x) printf("%5.0lf ", a[y][x]); puts("");
- } puts("");
- }
- void output2rt(double **a, size_t n, size_t m) {
- for (size_t y = 0; y < n; ++y) {
- for (size_t x = 0; x < m; ++x) printf("%14.10lf ", a[x][y]); puts("");
- } puts("");
- }
Решение задачи: «Malloc ошибка освобождения памяти»
textual
Листинг программы
- Len = wData * sizeof(**Data);
- Data = (double**)malloc(SizeArr * sizeof(*Data));
- for (i = 0; i < SizeArr; ++i) Data[i] = (double*)malloc(Len);
- Len = SizeArr * sizeof(double);
- Arr = (double**)malloc(SizeArr * sizeof(*Arr));
- for (i = 0; i < SizeArr; ++i) Arr[i] = (double*)malloc(Len);
- DT = (double**)malloc(3 * sizeof(*DT));
- for (i = 0; i < 3; ++i) DT[i] = (double*)malloc(Len);
- SU = (double**)malloc(SizeArr * sizeof(*SU));
- for (i = 0; i < SizeArr; ++i) SU[i] = (double*)malloc(Len);
- for (i = 0; i < SizeArr; ++i) free(Data[i]); free(Data); Data = NULL;
- for (i = 0; i < SizeArr; ++i) free(Arr[i]); free(Arr); Arr = NULL;
- for (i = 0; i < SizeArr; ++i) free(SU[i]); free(SU); SU = NULL;
- for (i = 0; i < 3; ++i) free(DT[i]); free(DT); DT = NULL;
- free(D0); D0 = NULL;
- free(D1); D1 = NULL;
Объяснение кода листинга программы
- Сначала мы вычисляем размер массива указателей на double, используя оператор sizeof.
- Затем мы используем функцию malloc для выделения памяти под массив указателей на double.
- Далее мы используем цикл for для выделения памяти под каждый элемент массива указателей на double, используя тот же размер, что и ранее.
- Мы повторяем шаги 2 и 3 для других массивов.
- Затем мы освобождаем память, используя функцию free, сначала для массива Data, затем для массива Arr, затем для массива SU, и, наконец, для массива DT.
- Мы также освобождаем память для отдельных double, используя функцию free.
- Наконец, мы устанавливаем указатели на NULL, чтобы освободить память.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д