Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
GibbonCho
0 / 0 / 0
Регистрация: 18.11.2013
Сообщений: 16
#1

Блок try catch жрет память - C++

18.11.2013, 12:45. Просмотров 1892. Ответов 48
Метки нет (Все метки)

Доброго времени суток! Проблема случилась там, где ее никак не ожидал, ответа ни в поисковиках, ни на форумах не нашел. Вся надежда на вас!

в общем есть блок
C++
1
2
3
4
5
try{
  //код, соединения с сервером или отправки сообщения серверу
} catch(Exception *e){
  //обработка ошибки подключения или отправки
}
Так вот при каждом исключении увеличивается память (в диспетчере задач).
Среда : C++ Builder 6

Без блока try catch память не растет, но приложение при ошибке перестает работать, естественно.
Читал о том, что в c++ у блока catch отсутствует деструктор. Еще читал про то, что если поставить ключ компиляции /EHa, то catch не будет кушать память..
Помогите, пожалуйста, весь интернет перерыл, не могу найти ответ.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.11.2013, 12:45
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Блок try catch жрет память (C++):

Программа с opencv жрет память - C++
Вообщем есть программа, после каждой итерации очищаю память, но все-равно почему то буквально за 2-3 цикла по j, программа падает из-за...

Блок try-catch - C++
В некоторых программах он хорошо работает и в блоке catch выводит то что написал, а в некоторых среда VS говорит "Необработанное исключение...

Работает ли указатель на базовый класс исключения, когда попадает в блок catch - C++
Работает ли указатель на базовый класс исключения, когда попадает в блок catch так же как обычно? То есть, если есть переопределенные...

Как передать управление в блок catch после системного исключения (компилятор g++)? - C++
Вот пример: не удаётся это сделать #include <windows.h> #include <stdio.h> //Эта функция- НОВЫЙ обработчик...

Один блок catch для двух типов исключений порожденных от одного класса - C++
Товагищи!! Имеется задача с книги С. Прата с++11. Не могу реализовать следующее : Вот к чему пришел #include <iostream> #include...

Как записать блок данных в память ? - C++
Есть ли какая нибудь функция типа fwrite(), которая может писать блоки данных разной длины, но из памяти в память ? Например есть...

48
Croessmah
Ушел
Эксперт CЭксперт С++
13554 / 7705 / 872
Регистрация: 27.09.2012
Сообщений: 19,006
Записей в блоге: 3
Завершенные тесты: 1
18.11.2013, 12:53 #2
А может где утечка в коде?
0
ПерС
375 / 291 / 90
Регистрация: 05.11.2013
Сообщений: 821
Записей в блоге: 5
Завершенные тесты: 1
18.11.2013, 12:54 #3
на сколько увеличивается?
память не обязана освобождаться сразу, маленькими порциями освобождать наоборот было бы невыгодней по ресурсам
0
SatanaXIII
Супер-модератор
Эксперт С++
5619 / 2654 / 247
Регистрация: 01.11.2011
Сообщений: 6,554
Завершенные тесты: 1
18.11.2013, 13:48 #4
Цитата Сообщение от Croessmah Посмотреть сообщение
А может где утечка в коде?
Да, покажите код, вызывающий эту утечку.
0
GibbonCho
0 / 0 / 0
Регистрация: 18.11.2013
Сообщений: 16
18.11.2013, 14:03  [ТС] #5
Без этого блока память не увеличивается... То есть я создавал 100 потоков и в каждом потоке был один и тот же код например отправки сообщения на сервер, но без try/catch. При первой же ошибке поток закрывался...

Память увеличивается примерно на 200-500 КБ за каждое исключение

Добавлено через 8 минут
А еще я вместо соединения или отправки сообщения в блок try засовывал что угодно, не вызывающее исключение (например тупо цикл)
Код
for(int i=0;i<1000000;i++){
  //что-то например считает
};
и в данном случае память не росла

Значит память растет именно при отлове исключений...

Добавлено через 2 минуты
Кстати, упомянул про ключ /EHa, но забыл спросить, где в билдере его можно указать?)
0
Tulosba
:)
Эксперт С++
4397 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
18.11.2013, 15:51 #6
Цитата Сообщение от GibbonCho Посмотреть сообщение
Значит память растет именно при отлове исключений...
Покажите код внутри try. По симптомам очень похоже, что просто не хватает надлежащих деструкторов, которые будут удалять объекты в случае срабатывания исключения. Например код:

C++
1
2
3
4
5
6
try
{
   init();
   action(); // Если здесь сработает исключение, destroy() не вызовется. 
   destroy();
}
Поэтому надо делать объект, который в конструкторе получает ресурсы, а в деструкторе удаляет.
Почитайте про RAII концепцию, в частности.
0
rangerx
1935 / 1544 / 141
Регистрация: 31.05.2009
Сообщений: 2,913
18.11.2013, 16:49 #7
Цитата Сообщение от GibbonCho Посмотреть сообщение
catch(Exception *e)
Каким образом генерируется исключение, что его приходится перехватывать по указателю?
0
GibbonCho
0 / 0 / 0
Регистрация: 18.11.2013
Сообщений: 16
18.11.2013, 16:49  [ТС] #8
Цитата Сообщение от Tulosba Посмотреть сообщение
Покажите код внутри try
Код
try{
  smtpClient->Send(message);
}
Вот например отправка инфы подписавшимся... Кстати, проблема действительно похоже не в catch(...)...
Я в try поместил запрос
Код
try{
  HTTP->Get("http://ksfjhgksjfgksjfgh.ru");
}
и не смотря на то, что исключения он ловил, память не росла. Каюсь, неправильно поставил диагноз..
Я так понимаю проблема в smtpClientе... Пользуюсь Indy 10...
0
Dreablin
5 / 5 / 1
Регистрация: 05.02.2010
Сообщений: 124
19.03.2015, 16:21 #9
Не знаю, чем закончили ваши изыскания, но у меня похожая проблема.
Вот этот од жрет память.
C++
1
2
3
4
5
6
7
try {
                tmp_data_str = IdHTTP1->Get(tmp_request_str);
            }
            catch (...) {
             ofs<< "исключение http" << std::endl;
//               устройство не найдено.
            }
Если просто
C++
1
tmp_data_str = IdHTTP1->Get(tmp_request_str);
То не жрет, но и не работает- поток выключается.
внутри tmp_request_str находится строка "http://192.168.1.141/dvmh.cgi HTTP/1.1". - 141 меняется в цикле от 0 до 255
Смысл в том, что поток в цикле пробегает по сети и ищет определенные устройства.
Все равботает, но пропадает по 4 кб в 10-20 секунд.
Код, котоырй находится дальше никак не влияет на эту ситуацию, если его весь убрать, все равно память утекает.

На всяий случай весь код:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    int tmp_device_num;
    bool is_device_known=false;
    UnicodeString tmp_data_str="";
    UnicodeString tmp_ip_str;
    UnicodeString tmp_request_str;
    UnicodeString tmp_str_to_comp="Emfit";
    UnicodeString tmp_dev_ID;
 
    myDeviceResponse tmp_responce;
 
    TIdHTTP *IdHTTP1 = new TIdHTTP;
 
    IdHTTP1->Request->UserAgent= "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0";
    IdHTTP1->Request->Accept= "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
    IdHTTP1->Request->AcceptLanguage= "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3";
    IdHTTP1->Request->AcceptEncoding= "gzip, deflate";
    IdHTTP1->Request->Connection= "keep-alive";
    IdHTTP1->Request->CacheControl= "max-age=0";
    IdHTTP1->ConnectTimeout = 100;
    while (1)
    {
        for (size_t i = 1; i < 255; i++)
        {
            tmp_ip_str= base_ip_str+(UnicodeString)i ;
            tmp_request_str="http://"+tmp_ip_str+"/dvmh.cgi HTTP/1.1";
 
            IdHTTP1->Request->Host=tmp_ip_str;
            try {
                tmp_data_str = IdHTTP1->Get(tmp_request_str);
            }
            catch (...) {
//               устройство не найдено.
            }
 
            if (tmp_data_str!="")   //ответ не пустой
            if (tmp_data_str[8] == tmp_str_to_comp[1])   //в сети могут быть и другие устройства
                {
                tmp_responce=Form1->DataParcer(tmp_data_str); // разберем ответ, что бы получить ID
 
                if (!Form1->FindDevByID(tmp_responce.dev_id))  // Если устройства с полученным ID нет в списке
                {
                    myDevice* tmp_dev = new myDevice;
                    tmp_dev->dev_ID=tmp_responce.dev_id;
                    tmp_dev->dev_ip=tmp_ip_str;
                    tmp_dev->unavailable_times=0;
                    vec_device_list.push_back(tmp_dev);
                }
 
 
 
        }
            tmp_data_str="";
            is_device_known=false;
        }
 
 
 
Synchronize(UpdateInfo);
    }
0
MrGluck
Модератор
Эксперт CЭксперт С++
7492 / 4607 / 693
Регистрация: 29.11.2010
Сообщений: 12,602
19.03.2015, 16:45 #10
C++
1
TIdHTTP *IdHTTP1 = new TIdHTTP;
Запихните в smart pointer.
C++
1
std::unique_ptr<TIdHTTP> IdHTTP1(new TIdHTTP);
0
Dreablin
5 / 5 / 1
Регистрация: 05.02.2010
Сообщений: 124
20.03.2015, 00:40 #11
Цитата Сообщение от MrGluck Посмотреть сообщение
Запихните в smart pointer.
Не помогло. Да и не должно. Он всего 1 раз создается вне цикла.
0
MrGluck
Модератор
Эксперт CЭксперт С++
7492 / 4607 / 693
Регистрация: 29.11.2010
Сообщений: 12,602
20.03.2015, 00:54 #12
Ну это единственное место, где явно идёт выделение динамической памяти без освобождения.

А метод Get случайно объекты внутри себя через new не выделяет?
0
Tulosba
:)
Эксперт С++
4397 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
20.03.2015, 07:44 #13
MrGluck, см. 42 строку. Мне кажется в 32й надо просто выйти через return, предварительно освободив idHTTP1.
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.03.2015, 08:36 #14
GibbonCho, ели исключение не обработать, а оно не обрабатывается т.к нет e->Delete то и будет течь.
Все пишушие здесь "эксперты подсказчики" реально думают "что скобочки с тремя точечками за вас всю работу сделают"?
единственное что делает "3-х точечный кэтч catch" - сбросит флаг ошибки в тред контексте чтобы треда не дохла, освобождение ресурсов осуществляет конрктеный класс эксепшина и то не всегда
Это код в зубы чтобы понятно было
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
 
int main(){
    char * str;
    system("pause");
    //Пример утечки в 10 Мб
    for( size_t i = 0; i < 10; i++ ){
        try{
            str = new char[1024*1024];
            throw(0);
        }
        catch(...){
            cerr<<"exception #"<<i + 1<<endl;
        }
    }
    system("pause");
    return 0;
}
0
Миниатюры
Блок try catch жрет память   Блок try catch жрет память  
-=ЮрА=-
20.03.2015, 08:46     Блок try catch жрет память
  #15

Не по теме:

Цитата Сообщение от rangerx Посмотреть сообщение
Каким образом генерируется исключение, что его приходится перехватывать по указателю?
- почти все виндовые эксепшины так генятся хотябы приславутый CMemoryException
https://msdn.microsoft.com/en-us/library/97z4sxfb.aspx

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.03.2015, 08:46
Привет! Вот еще темы с ответами:

много памяти жрет игра на OpenGL - C++
много памяти жрет игра на OpenGL...через диспетчер смотрю аж 15 метров...там же ничего особого нету...или так и должно быть??? ...

Браузер Awesomium жрет память - C# WPF
Всем здравствуйте, у меня в программе используется компонент awesomium замечено что на некоторых сайтах (если долго открыт браузер) память...

Что то жрет оперативную память - Windows 7
мне посоветовали обратиться сюда насчет этой темыhttp://www.cyberforum.ru/viruses/thread1495290.html где мы не смогли найти решение может...

Отрисовка в таймере жрет память - OpenGL
Программа написанная на OpenGL понемногу, но непрерывно ест RAM. А именно после того как я юзаю таймер вида void Timer( int value ){...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
20.03.2015, 08:46
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru