Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
GibbonCho
0 / 0 / 0
Регистрация: 18.11.2013
Сообщений: 16
18.11.2013, 12:45     Блок try catch жрет память #1
Доброго времени суток! Проблема случилась там, где ее никак не ожидал, ответа ни в поисковиках, ни на форумах не нашел. Вся надежда на вас!

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

Без блока try catch память не растет, но приложение при ошибке перестает работать, естественно.
Читал о том, что в c++ у блока catch отсутствует деструктор. Еще читал про то, что если поставить ключ компиляции /EHa, то catch не будет кушать память..
Помогите, пожалуйста, весь интернет перерыл, не могу найти ответ.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
MakeEasy
38 / 38 / 13
Регистрация: 24.02.2015
Сообщений: 151
20.03.2015, 12:23     Блок try catch жрет память #21
Dreablin, Может быть подключения висят и в экспешене не закрываются. Можно попробовать убрать keep-alive :
C++
1
IdHTTP1->Request->Connection= "keep-alive";
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Dreablin
5 / 5 / 1
Регистрация: 05.02.2010
Сообщений: 124
20.03.2015, 13:13     Блок try catch жрет память #22
Цитата Сообщение от MakeEasy Посмотреть сообщение
Может быть подключения висят и в экспешене не закрываются. Можно попробовать убрать keep-alive :
Хорошая идея, но не прокатило ((
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
20.03.2015, 14:21     Блок try catch жрет память #23
Цитата Сообщение от Dreablin Посмотреть сообщение
То не жрет, но и не работает- поток выключается.
Потому что необработанное исключение, которое возникает в Get() отправляется на уровень выше, до того момента пока не встретит соответствующего обработчика. А если не встретит, то и вовсе будет вызван какой-нибудь std::terminate, который приведет к закрытию программы.
Когда ты добавляешь перехват всего и вся catch (...) не добавив внутри обработчика ничего вразумительного (код ты не привел по крайней мере), и не сделав выхода из функции или хотя бы из цикла, ты попадаешь на строки 35 и далее. В частности в 42 строке у тебя создается в куче элемент, указатель на который ты добавляешь в vec_device_list. С листом тоже не понятно что дальше происходит, удаляешь ты потом его элементы или нет (снова нет кода).
В первом приближении решение твоей задачи я описать чуть выше. Процитирую себя же:
Цитата Сообщение от Tulosba Посмотреть сообщение
Мне кажется в 32й надо просто выйти через return, предварительно освободив idHTTP1.
Сделай это и проверь как будут вести себя утечки. Если не поможет - приводи больше кода.

Добавлено через 43 секунды

Не по теме:

Цитата Сообщение от Dreablin Посмотреть сообщение
ты ответил на тему 3х летней давности.
В частности поэтому следует создавать новую тему.

Dreablin
5 / 5 / 1
Регистрация: 05.02.2010
Сообщений: 124
20.03.2015, 14:49     Блок try catch жрет память #24
Цитата Сообщение от Tulosba Посмотреть сообщение
В частности в 42 строке у тебя создается в куче элемент, указатель на который ты добавляешь в vec_device_list. С листом тоже не понятно что дальше происходит, удаляешь ты потом его элементы или нет (снова нет кода).
С листом происходит следующее - его опрашивает в цикле другой поток. Т.е. он никогда не должен удаляться впринципе. Если устройство подключено, оно будет работать без перерывов. Механизм удаления предусмотрен, если устройсвто пропадает, но это делает другой поток. Больше того, Если в сети вообще нет устройств (т.е. в 42ю строку мы не попадаем). Расписав все Catch, как это было в самом начале:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//catch(EIdSocketError &E)  // Исключения сокетов
// {
//   ShowMessage("Ошибка:\n\""+E.Message+"\"");
// }
//catch(EIdHTTPProtocolException &E)
// {
//   // Можно получить код ответа сервера  HTTP  через E.ErrorCode
//      ShowMessage(String(E.ErrorCode)+" "+E.Message); break;
//  }
//catch(EIdException &E)// Другие исключения Indy
//  {
//   ShowMessage("Ошибка:\n\""+E.Message+"\"");
//  }
//catch(Exception &E)   // Другие НЕ Indy искключения
//  {
//  ShowMessage("Ошибка:\n\""+E.Message+"\"");
//  }

Вылетает ошибка "Connection time out". Ошибка возникает уже на 192.168.1.1 и если выходить через return, то смысла с этого потока?
И это весь код. Бежит по сети, находит - добавляет.
Я создал новый проект с таким кодом:
Кликните здесь для просмотра всего текста
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
60
61
62
63
64
65
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    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;
 
//  std::unique_ptr<TIdHTTP> IdHTTP1(new TIdHTTP);
    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("http://192.168.1.149/dvmh.cgi HTTP/1.1");
            }
//          catch (...) {
//           ofs<< "исключение http" << std::endl;
//               устройство не найдено.
//          }
catch(EIdSocketError &E)  // Исключения сокетов
 {
   ShowMessage("Ошибка:\n\""+E.Message+"\"");
 }
catch(EIdHTTPProtocolException &E)
 {
   switch(E.ErrorCode)
      {
        ShowMessage(String(E.ErrorCode)+" "+E.Message); break;
      }
  }
catch(EIdException &E)// Другие исключения Indy
  {
     ShowMessage("Ошибка:\n\""+E.Message+"\"");
  }
catch(Exception &E)   // Другие НЕ Indy искключения
  {
    ShowMessage("Ошибка:\n\""+E.Message+"\"");
  }
 
catch(...)   // Другие искключения
  {
    ShowMessage("Ошибка");
  }
}
 
}


Он опрашиваетадрес, по которому точно нет устройства. Ошиба с таймаутом есть и память жрет.
Если поставить адрес, где устройство есть, память не жрет.
Проблема, значит в connection time out - где-то остается висеть соединение... Но где?...
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
20.03.2015, 15:17     Блок try catch жрет память #25
Цитата Сообщение от Dreablin Посмотреть сообщение
Вылетает ошибка "Connection time out".
Это по какому типу исключения?
Строку 45 надо убрать, и break в 48. Иначе это глупая конструкция.
Цитата Сообщение от Dreablin Посмотреть сообщение
и память жрет.
Кстати, чем ты это наблюдаешь и какой порядок жора?
Сдается мне, проблема твоя скорее всего в неправильной работе с Indy компонентами. Хотя может и в самих компонентах баг.

Добавлено через 4 минуты
Цитата Сообщение от Dreablin Посмотреть сообщение
Проблема, значит в connection time out
Кстати, посмотри каким-нибудь ProcessExplorer список TCP-соединений у процесса.
Чтобы точно понять они плодятся или нет.

Добавлено через 2 минуты
Ну и ещё, возможно в случае неудачи имеет смысл подождать (Sleep) прежде чем снова ломиться (Get) в ту же самую дырку.
Dreablin
5 / 5 / 1
Регистрация: 05.02.2010
Сообщений: 124
20.03.2015, 15:34     Блок try catch жрет память #26
Цитата Сообщение от Tulosba Посмотреть сообщение
Это по какому типу исключения?
C++
1
2
3
4
catch(EIdException &E)// Другие исключения Indy
  {
     ShowMessage("Ошибка2:\n\""+E.Message+"\"");
  }
Цитата Сообщение от Tulosba Посмотреть сообщение
Кстати, чем ты это наблюдаешь и какой порядок жора?
Наблюдаю windows explorerом стандратным. Порядок 1 мб в 2-3 часа
Цитата Сообщение от Tulosba Посмотреть сообщение
Кстати, посмотри каким-нибудь ProcessExplorer список TCP-соединений у процесса.
Тот же монитор ресурсов показывает целый список TCP соединений у процесса... Не столько, сольок их должно быть при такой работе, но все равно десятки. Видимо рано или поздно соединения закрываются на другом уровне, а вот память не освобождается....
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
20.03.2015, 15:57     Блок try catch жрет память #27
Цитата Сообщение от Dreablin Посмотреть сообщение
1 мб в 2-3 часа
И сколько итераций цикла за эти 2-3 часа проходит?
Любопытно как ты вообще обратил внимание на этот мегабайт за 2 часа.
Цитата Сообщение от Dreablin Посмотреть сообщение
Наблюдаю windows explorerом стандратным
Ты наверное имел в виду TaskManager?
Цитата Сообщение от Dreablin Посмотреть сообщение
рано или поздно соединения закрываются на другом уровне, а вот память не освобождается....
Есть такое понятие как "полуоткрытое" соединение. Это когда запрос о TCP подключении отправили, а ответа не получили ещё (SYN_WAIT вроде называется состояние). Разумеется эти соединения кушают какую-то память (пока они висят в ожидании), но если они завершились по причине таймаута, то утечек быть не должно. Т.к. это всё на уровне стека TCP/IP обеспечивается, а не в клиентской части программы.

Таким образом твои утечки может быть и не утечки вовсе, а естественный расход на поддержку N-го кол-ва полуоткрытых соединений.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.03.2015, 16:00     Блок try catch жрет память #28
Цитата Сообщение от ПерС Посмотреть сообщение
память не обязана освобождаться сразу, маленькими порциями освобождать наоборот было бы невыгодней по ресурсам
С чего это?
Dreablin
5 / 5 / 1
Регистрация: 05.02.2010
Сообщений: 124
20.03.2015, 16:09     Блок try catch жрет память #29
Цитата Сообщение от Tulosba Посмотреть сообщение
Любопытно как ты вообще обратил внимание на этот мегабайт за 2 часа.
Тестированием на ночь, например. Да и видно само по себе. Съедает 4кб за 10-30 секунд, примерно.
Если вечером оставить уже будет 6 мб вместо 2х.
Если еще не понятно, этот код должен работать неограниченное время.
Цитата Сообщение от Tulosba Посмотреть сообщение
Таким образом твои утечки может быть и не утечки вовсе, а естественный расход на поддержку N-го кол-ва полуоткрытых соединений.
Сомнительно. Оставлял работать на 4-5 дней, записал в базу около 5 млн записей, все работает. Но расход памяти был стабильный. Это именно утечка и происходит она во время исключения GET при обработе его в Catch.
Возможно, дело можно решить настройкой Indy, что бы вместо connection time out, соединение автоматически закрывалось, если нет ответа.... Пока не нашел выход.
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
20.03.2015, 16:18     Блок try catch жрет память #30
Цитата Сообщение от Dreablin Посмотреть сообщение
Съедает 4кб за 10-30 секунд,
Лучше посчитать именно на кол-во итераций цикла, секунды ничего не говорят, если не знаешь сколько раз действие было выполнено на это время.
Цитата Сообщение от Dreablin Посмотреть сообщение
Оставлял работать на 4-5 дней,
Т.е. за 5 суток ~60 метров набегало в плюс?
Dreablin
5 / 5 / 1
Регистрация: 05.02.2010
Сообщений: 124
20.03.2015, 17:06     Блок try catch жрет память #31
Цитата Сообщение от Tulosba Посмотреть сообщение
Т.е. за 5 суток ~60 метров набегало в плюс?
Около того.
Цитата Сообщение от Tulosba Посмотреть сообщение
Лучше посчитать именно на кол-во итераций цикла, секунды ничего не говорят, если не знаешь сколько раз действие было выполнено на это время.
400 кб за 12700 попыток Get
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
20.03.2015, 17:47     Блок try catch жрет память #32
Dreablin, я думаю надо копаться в Indy. Но тут я вряд ли смогу помочь. Кстати, если ещё не видел эту тему, обрати внимание:
http://stackoverflow.com/questions/5...ed-for-indy-10
-=ЮрА=-
Заблокирован
Автор FAQ
20.03.2015, 22:07     Блок try catch жрет память #33
Цитата Сообщение от Dreablin Посмотреть сообщение
К сожалению, ты ответил на тему 3х летней давности. Я написал в ней же, у меня схожая проблема, но никого new в try нет. Никакой динамики в икле нет, а память уходит... Мой код на пару сообщений выше
- почему к сожалению?По поводу памяти
Цитата Сообщение от Dreablin Посмотреть сообщение
try {
* * * * * * * * tmp_data_str = IdHTTP1->Get(tmp_request_str);
* * * * * * }
- в try{}catch() повешен метод Get, как я понимаю речь идёт об HTTP протоколе, для начала хотелось бы увидеть начинку метода. Если же метод в статической либе то почти 100% в методе идёт нечто аля
C++
1
2
char * buffer = new char[1 + bufSize];
recv(socket, buffer);// вот навернулся recv - улетела память
Добавлено через 2 минуты
Касательно исключений - для начала делаем
C++
1
2
3
4
5
6
7
try{
    //наша лапша из кода
}
catch(CException *e){
    e->ReportError();//узнаём что случилось
    e->Delete();//пробуем кроме сброса флага пофиксить испорченный thread context
}
Более детально могу разрулить лишь когда увижу полный сегмент кода с утечкой

Добавлено через 1 минуту
Вот пример использования API для работы с Win - эксепшинами https://msdn.microsoft.com/en-us/library/97z4sxfb.aspx

Добавлено через 1 минуту

Не по теме:

Dreablin, короче давай в студию начинку

Цитата Сообщение от Dreablin Посмотреть сообщение
tmp_data_str = IdHTTP1->Get("http://192.168.1.149/dvmh.cgi HTTP/1.1");



Добавлено через 2 минуты
Цитата Сообщение от ForEveR Посмотреть сообщение
Что? Освобождение ресурсов осуществляет конкретный класс эксепшна? Только если ресурсов выделенных внутри данного класса исключения...
Не по теме:
Сообщение от -=ЮрА=-
так что у меня свои методы восстановления справедливости.
Справедливость должна быть восстановлена! (c) Утер Светоносный
- ну тогда тебе тоже сюда https://msdn.microsoft.com/en-us/lib...(v=vs.60).aspx почитай немного литературки о том как происходит обработка исключений в Win а то как то неканает твоё удивление. конкретный CXtypeException вызывает конкретную обработку исключительной ситуации и конкретный класс CXtypeException сбрасывает флаг ошибки + производит на сколько это возможно возвращение стека.

Добавлено через 1 минуту

Не по теме:

Да ForEveR добавлю что CEception является базовым классом для обработки исключений(способен вызвать необходимый обработчик), хотя лан чё мне тебя учить ты ж вроди как тут "светило", думаю msdn открыть сможешь. Короче жду тебя)

castaway
Эксперт С++
4841 / 2980 / 367
Регистрация: 10.11.2010
Сообщений: 11,012
Записей в блоге: 10
Завершенные тесты: 1
20.03.2015, 22:26     Блок try catch жрет память #34
-=ЮрА=-, речь о обычных исключениях языка C++.
С чего ты вообще взял что речь идёт именно о ОС Windows?
Какого хрена ты приплетаешь сюда какие-то CXtypeException и CEception? В языке нет таких терминов.
Почитай хоть раз нормальную книгу по C++ вместе со наброском стандарта. Ты слишком сильно застопорился со своим древним как говно мамонта MFC.
-=ЮрА=-
Заблокирован
Автор FAQ
20.03.2015, 22:35     Блок try catch жрет память #35
-=ЮрА=-, речь о обычных исключениях языка C++.
С чего ты вообще взял что речь идёт именно о ОС Windows?
- с чего взял, да вот с вот этого
C++
1
2
3
4
5
6
[quote="GibbonCho;5350935"]1
try{
* //код, соединения с сервером или отправки сообщения серверу
} catch(Exception *e){
* //обработка ошибки подключения или отправки
}[/quote]
- мне это похоже на обычное ВИН CException
Да ForEveR, это для тебя
Цитата Сообщение от ForEveR Посмотреть сообщение
Что? Освобождение ресурсов осуществляет конкретный класс эксепшна?
- смотри сам
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
#include <afx.h>
#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(new CMemoryException());
            
        }
        catch( CMemoryException * e)
        {
            e->ReportError(MB_OK, 0);
            e->Delete();
            cerr<<"exception #"<<i + 1<<endl;
        }
    }
    system("pause");
    return 0;
}
будь добр сравни показания диспетчера для поста 14 с этими скриншотами(хотя нет ты у себя слинкуй да погляди). Заметил рестор памяти от итерации к итерации начиная со 2-й?В первой итерации произошли изменения в тредконтексте потому немного памяти съелось, после всё оставалось на уровне.
Миниатюры
Блок try catch жрет память   Блок try catch жрет память  
Voivoid
 Аватар для Voivoid
580 / 256 / 12
Регистрация: 31.03.2013
Сообщений: 1,283
20.03.2015, 23:38     Блок try catch жрет память #36
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
мне это похоже на обычное ВИН CException
Ох, лол, точно. Даже не обратил внимание ( и похоже не я один ), что там указатель. Кроме как в MFC такой дичью вроде никто больше не пользуется, так что похоже действительно оно ( ну или топикстартер просто опечатался ). Приношу извинения за, как оказалось, неуместное троллирование.
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
21.03.2015, 07:38     Блок try catch жрет память #37
Voivoid, топикстартеров тут два: один 2013 года с указателем - GibbonCho, другой 2015 со ссылками (см. например код в сообщении #24) - Dreablin. Проблемы первого уже никто в здравом уме тут не обсуждает.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
21.03.2015, 09:49     Блок try catch жрет память #38
-=ЮрА=-, Соглашусь, мое сообщение было не совсем уместно. MFC я абсолютно не знаю. Спасибо за объяснение.
-=ЮрА=-
Заблокирован
Автор FAQ
21.03.2015, 09:50     Блок try catch жрет память #39
GibbonCho, Dreablin, по прежнему жду полный листинг метода Get на котором улетала память, увижу код скажу конкретно где как и что текло.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.03.2015, 10:31     Блок try catch жрет память
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
21.03.2015, 10:31     Блок try catch жрет память #40
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
жду полный листинг метода Get на котором улетала память
Если ты ещё не понял, оба ТС используют библиотеку Indy. Get - метод класса этой библиотеки. Хочешь полного кода - качай исходники Indy. Только учти что она писана на Delphi.
Зачем ты сюда приплел MFC и начал баламутить тему подходами от MS я могу только догадываться. ТСы пользуются C++ Builder'ом (RAD Studio), никакой связи с MFC тут и в помине нет.
Yandex
Объявления
21.03.2015, 10:31     Блок try catch жрет память
Ответ Создать тему
Опции темы

Текущее время: 12:23. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru