Russian Qt Forum
Ноябрь 25, 2024, 06:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Программе не хватает памяти?  (Прочитано 6723 раз)
daruma
Гость
« : Январь 10, 2018, 19:19 »

Добрый день!
Пишу программу с большим количеством вычислений. Много раз делается преобразование Фурье, много больших массивов (разные производные).
Отдельно Фурье работает, проверяла.
Код выглядит примерно так:

Код:
    double HMatrixFourRe[ImageHeight * ImageWidth];
    double HMatrixFourIm[ImageHeight * ImageWidth];
    double Denominator;

    Fourier(HMatrix, HMatrixFourRe, HMatrixFourIm, ImageWidth, ImageHeight, ImageWidth, ImageHeight);

    double WxFourRe[ImageHeight * ImageWidth];
    double WxFourIm[ImageHeight * ImageWidth];

    double WyFourRe[ImageHeight * ImageWidth];
    double WyFourIm[ImageHeight * ImageWidth];

    double Delta[ImageWidth * ImageHeight];

    if(ImageIRe == NULL)
    {
        ImageIRe = new double[ImageHeight * ImageWidth];
        ImageIIm = new double[ImageHeight * ImageWidth];
        Fourier(ImageI, ImageIRe, ImageIIm, ImageWidth, ImageHeight, ImageWidth, ImageHeight);
    }

    Fourier(Wx, WxFourRe, WxFourIm, ImageWidth, ImageHeight, ImageWidth, ImageHeight);
    Fourier(Wy, WyFourRe, WyFourIm, ImageWidth, ImageHeight, ImageWidth, ImageHeight);

    double ImageLFourReDerXL[ImageHeight * ImageWidth];
    double ImageLFourImDerXL[ImageHeight * ImageWidth];

    //dx
    Fourier(ImageLXDerivate, ImageLFourReDerXL, ImageLFourImDerXL, ImageWidth, ImageHeight, ImageWidth, ImageHeight);

    double ImageLFourReDerYL[ImageHeight * ImageWidth];
    double ImageLFourImDerYL[ImageHeight * ImageWidth];

    //dy
    Fourier(ImageLYDerivate, ImageLFourImDerYL, ImageLFourReDerYL, ImageWidth, ImageHeight, ImageWidth, ImageHeight);

Внутри Фурье постоянно возникает ошибка SIGSEGV. Если все массивы выделяю сразу, ошибка будет на первом же Фурье, если вот так последовательно - на последнем Фурье.
Это код внутри Фурье, ошибка возникает внутри цикла при row = 0:
Код:
double ColumnIn[ArrInHeight];
for(long row = 0; row < ArrInHeight; row++)
{
      ColumnIn[row] = ArrIn[row * ArrInWidth + col]; //здесь возникает ошибка
}

Проблема именно в ColumnIn (проверяла). Я плохо в таких вещах разбираюсь, как узнать, в чём именно проблема? (может стек переполнился... понятия не имею).

ОС: ubuntu14.04 LTS, 64-битная.
Оперативки: 2 гига.

Если кто-нибудь может подсказать, буду очень благодарна.
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #1 : Январь 10, 2018, 22:18 »

когда под отладчиком запускаешь - что показывает в момент сбоя ?

делай минимальный рабочий проект, выкладывай на гитхаб, иначе разговор впустую

зы а почему 1404 ?
« Последнее редактирование: Январь 10, 2018, 22:20 от qate » Записан
zhbr
Гость
« Ответ #2 : Январь 11, 2018, 06:49 »

стэк кончился? может массивы динамически выделять?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Январь 11, 2018, 07:40 »

Выделять на стеке приличный массив не годится. Используйте контейнеры, хотя бы так
Код
C++ (Qt)
std::vector<double> ImageLFourReDerYL[ImageHeight * ImageWidth];
std::vector<double> ImageLFourImDerYL[ImageHeight * ImageWidth];
 
//dy
Fourier(ImageLYDerivate, &ImageLFourImDerYL[0], &ImageLFourReDerYL[0], ImageWidth, ImageHeight, ImageWidth, ImageHeight);
 
Еще лучше переписать ф-цию Fourier чтобы она тоже принимала контейнеры (это несложно), Сейчас это слишком длинная сопля, вызывать ее очень неудобно.

Вторая проблема
Код:
    if(ImageIRe == NULL)
    {
        ImageIRe = new double[ImageHeight * ImageWidth];
        ImageIIm = new double[ImageHeight * ImageWidth];
        Fourier(ImageI, ImageIRe, ImageIIm, ImageWidth, ImageHeight, ImageWidth, ImageHeight);
    }
Память выделенную под массивы надо затем освобождать с помощью delete []. Но здесь просто дописать delete [] в конце этого куска кода будет ошибкой т.к. ImageIRe мог быть и "не наш". Опять лучше задействовать контейнер, напр
Код
C++ (Qt)
size_t totalSize = ImageHeight * ImageWidth;
if (ImageIRe.size() != totalSize)
   {
       ImageIRe.resize(totalSize);
       ImageIIm.resize(totalSize);
       Fourier(ImageI, &ImageIRe[0], &ImageIIm[0], ImageWidth, ImageHeight, ImageWidth, ImageHeight);
   }
Записан
daruma
Гость
« Ответ #4 : Январь 11, 2018, 15:55 »

когда под отладчиком запускаешь - что показывает в момент сбоя ?

делай минимальный рабочий проект, выкладывай на гитхаб, иначе разговор впустую

зы а почему 1404 ?

Указывает на эту строчку и выводит Segmentation Fault. Больше никакой информации нет. Проблема именно в доступе к массиву,который выделен парой строк выше, отдельно код работает, поэтому кроме нехватки памяти у меня никаких идей нет...
Я причешу код и выложу.

PS
Потому что с виндой у меня не клеится, а последний раз обновляла систему очень давно (по принципу: пока всё работает и слава богу, не дышите на комп Улыбающийся ).
Записан
daruma
Гость
« Ответ #5 : Январь 11, 2018, 16:06 »

Выделять на стеке приличный массив не годится. Используйте контейнеры, хотя бы так
То есть они по-разному хранятся?

Цитировать
Память выделенную под массивы надо затем освобождать с помощью delete []. Но здесь просто дописать delete [] в конце этого куска кода будет ошибкой т.к. ImageIRe мог быть и "не наш".
Массив удаляется, но уже в самом конце, тк он почти всё время используется. Остальные массивы "временные", их значения вычисляются заново на каждой итерации, поэтому я не выделяла их динамически.
Записан
daruma
Гость
« Ответ #6 : Январь 11, 2018, 16:13 »

стэк кончился? может массивы динамически выделять?

Это всё внутри функции, не уверена, что динамическое выделение чем-то поможет. Дальше идёт кусок кода, где это безобразие ещё по сто раз используется, то есть всё равно удалить ничего нельзя. Я поставила где можно области видимости, но это не спасло, ошибка стала вылезать на пару строк ниже (собственно, на этом моменте фантазия и истощилась).

В общем, выложу проект, а пока буду про хранение объектов в памяти читать.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Январь 11, 2018, 16:26 »

Массив удаляется, но уже в самом конце, тк он почти всё время используется. Остальные массивы "временные", их значения вычисляются заново на каждой итерации, поэтому я не выделяла их динамически.
Девонька, учите контейнеры, чем быстрее - тем лучше. Без них тут можно долго пыль глотать
Записан
Apktyc
Самовар
**
Offline Offline

Сообщений: 133


Просмотр профиля
« Ответ #8 : Январь 11, 2018, 16:28 »

Если грубо, то:
Стек - маленький (пару мегабайт) и быстрый.
Куча - большая (уже гигабайты) и медленная.

У Вас идет выделение на стеке массивов для типа double (8 байт), на моей рабочей машине строчка
Код:
double Array[512 * 512]
уже вызывает SIGSEGV
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #9 : Январь 11, 2018, 21:39 »

Если грубо, то:
Стек - маленький (пару мегабайт) и быстрый.
Куча - большая (уже гигабайты) и медленная.

как это ?
я думал и стек и куча - это одна и та же память
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Январь 11, 2018, 21:43 »

как это ?
я думал и стек и куча - это одна и та же память
Имеется ввиду скорость аллокации.
Записан
daruma
Гость
« Ответ #11 : Январь 14, 2018, 14:05 »

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

Контейнеры решили все проблемы. Спасибо!
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.097 секунд. Запросов: 22.