msvc 2010, rtti memory leak ?
От: stil.man  
Дата: 27.07.13 12:34
Оценка:
Салют.
Вот такая интересная ситуация.

struct vvv
{};
struct vvv1
{};

void f()
{
  std::cout << typeid(vvv).name() << std::endl;
  std::cout << typeid(vvv1).name() << std::endl;
  std::cout << "finished" << std::endl;
}

int main(int argc, char** argv) 
{
  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
  boost::thread(boost::bind(f));
  std::cout << "wait" << std::endl;
  Sleep(1000);
  std::cout << "wait" << std::endl;
  Sleep(1000);
  return 0;
}

Компилируем в Visual Studio 2010 (x64/Debug), запускаем и видим:
Detected memory leaks!
Dumping objects ->
{99} normal block at 0x0000000000CF7C20, 12 bytes long.
 Data: <struct vvv1 > 73 74 72 75 63 74 20 76 76 76 31 00 
{98} normal block at 0x0000000000CF7BA0, 16 bytes long.
 Data: < |       z      > 20 7C CF 00 00 00 00 00 B0 7A CF 00 00 00 00 00 
{97} normal block at 0x0000000000CF7B30, 11 bytes long.
 Data: <struct vvv > 73 74 72 75 63 74 20 76 76 76 00 
{96} normal block at 0x0000000000CF7AB0, 16 bytes long.
 Data: <0{              > 30 7B CF 00 00 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.


При этом, если запускать это в основном потоке, утечки не наблюдается.
Очевидно так же, что к моменту выхода из main, второй поток уже завершился.
Как с этим жить ?
Re: msvc 2010, rtti memory leak ?
От: omgOnoz  
Дата: 27.07.13 13:55
Оценка:
это полный вывод консоли?
Re[2]: msvc 2010, rtti memory leak ?
От: stil.man  
Дата: 27.07.13 14:58
Оценка:
Здравствуйте, omgOnoz, Вы писали:

O>это полный вывод консоли?

Если вы имеете в виду отладочный вывод, то вот он весь:

'ddddddd.exe': Loaded 'C:\Users\andrey.sabelnikov\Documents\Visual Studio 2010\Projects\ddddddd\x64\Debug\ddddddd.exe', Symbols loaded.
'ddddddd.exe': Loaded 'C:\Windows\System32\ntdll.dll', Symbols loaded (source information stripped).
'ddddddd.exe': Loaded 'C:\Windows\System32\kernel32.dll', Symbols loaded (source information stripped).
'ddddddd.exe': Loaded 'C:\Windows\System32\KernelBase.dll', Symbols loaded (source information stripped).
The thread '_threadstartex' (0x6c90) has exited with code 0 (0x0).
Detected memory leaks!
Dumping objects ->
{99} normal block at 0x0000000000D97C20, 12 bytes long.
 Data: <struct vvv1 > 73 74 72 75 63 74 20 76 76 76 31 00 
{98} normal block at 0x0000000000D97BA0, 16 bytes long.
 Data: < |       z      > 20 7C D9 00 00 00 00 00 B0 7A D9 00 00 00 00 00 
{97} normal block at 0x0000000000D97B30, 11 bytes long.
 Data: <struct vvv > 73 74 72 75 63 74 20 76 76 76 00 
{96} normal block at 0x0000000000D97AB0, 16 bytes long.
 Data: <0{              > 30 7B D9 00 00 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.
The program '[0xB2A4] ddddddd.exe: Native' has exited with code 0 (0x0).

Для конкретно этого запуска я убедился что 0x6c90 — это второй тред.
В выводе консоли нет ничего содержательного.
Re: msvc 2010, rtti memory leak ?
От: Caracrist https://1pwd.org/
Дата: 27.07.13 21:46
Оценка:
Здравствуйте, stil.man, Вы писали:

SM>При этом, если запускать это в основном потоке, утечки не наблюдается.

SM>Очевидно так же, что к моменту выхода из main, второй поток уже завершился.
SM>Как с этим жить ?

Допустим память выделяется динамически под запрос один раз в куче рантайма.
Это считается утечкой?
~~~~~
~lol~~
~~~ Single Password Solution
Re: msvc 2010, rtti memory leak ?
От: Kubyshev Andrey  
Дата: 28.07.13 02:07
Оценка:
Имхо, Нужно join() thread;
ф-ция потока завершилась, но thread не исчез.
Re: msvc 2010, rtti memory leak ?
От: uzhas Ниоткуда  
Дата: 28.07.13 07:41
Оценка:
Здравствуйте, stil.man, Вы писали:

SM>Очевидно так же, что к моменту выхода из main, второй поток уже завершился.

SM>Как с этим жить ?

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

ссылки по теме:
http://stackoverflow.com/questions/4508181/thread-destructors-in-c0x-vs-boost
http://stackoverflow.com/questions/5874493/why-is-destructor-of-boostthread-detaching-joinable-thread-instead-of-calling
Re: msvc 2010, rtti memory leak ?
От: Pavel Dvorkin Россия  
Дата: 28.07.13 16:06
Оценка: 2 (1)
Здравствуйте, stil.man, Вы писали:

Дело в том, что в Visual C++ main вызывается из стартового (он же финишный) код. Убедиться в этом, а заодно и посмотреть на него проще простого — ставим брекпойнт на закрывающую фигурную скобку main, по достижении брекпойнта нажимает F11 и оказываемся там. Если дальше этот код протрассировать, то дойдем до ExitProcess. А ExitProcess убивает все потоки и заканчивает процесс. Память, выделенная при запуске потока стартовым кодом потока (а его посмотреть также несложно, протрассировав __beginthreadex) остается неосвобожденной, так как нормального окончания потока по прямому (явный вызов_endthreadex) или косвенному (вызов _endthreadex в финишном коде потока после выхода на закрывающую фигурную скобку потоковой функции) не произошло.
Вот и все.
With best regards
Pavel Dvorkin
Re[2]: msvc 2010, rtti memory leak ?
От: stil.man  
Дата: 29.07.13 12:53
Оценка:
Здравствуйте, Caracrist, Вы писали:

C>Здравствуйте, stil.man, Вы писали:


SM>>При этом, если запускать это в основном потоке, утечки не наблюдается.

SM>>Очевидно так же, что к моменту выхода из main, второй поток уже завершился.
SM>>Как с этим жить ?

C>Допустим память выделяется динамически под запрос один раз в куче рантайма.

C>Это считается утечкой?
Получается что с точки зрения из собственного рантайма считается. Это он мне показывает что это утечки.
Re[2]: msvc 2010, rtti memory leak ?
От: stil.man  
Дата: 29.07.13 13:01
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, stil.man, Вы писали:


SM>>Очевидно так же, что к моменту выхода из main, второй поток уже завершился.

SM>>Как с этим жить ?

U>моя личная рекомендация: программа всегда должна дожидаться своих порожденных потоков, вызовите join

Ваша личная очевидная рекомендация кэп, никак не решает описанную проблему.
int main(int argc, char** argv) 
{
  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
  boost::thread th = boost::thread(boost::bind(f));
  std::cout << "wait join" << std::endl;
  th.join();
  std::cout << "joined ok" << std::endl;
  return 0;
}

Те же самые утечки.
Re[3]: msvc 2010, rtti memory leak ?
От: uzhas Ниоткуда  
Дата: 29.07.13 13:12
Оценка:
Здравствуйте, stil.man, Вы писали:

SM>Те же самые утечки.


предположу, что утечки связаны не с механизмом запуска потоков, а с содержимым функции f
1) уберите доп. потоки, вызовите функцию f из main, проверьте утечки
2) уберите вызов typeid из f, выполните ее в другом потоке, проверьте утечки

если утечки в пункте 1) остались, то снова предположу, что связано это с вызовом typeid, ведь данная функция должна возвращать ссылку на typeinfo. время жизни этого объекта должно переживать приложение (в стандарте более точно описано как долго должна жить ссылка)
Re[2]: msvc 2010, rtti memory leak ?
От: stil.man  
Дата: 29.07.13 13:15
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, stil.man, Вы писали:


PD>Дело в том, что в Visual C++ main вызывается из стартового (он же финишный) код. Убедиться в этом, а заодно и посмотреть на него проще простого — ставим брекпойнт на закрывающую фигурную скобку main, по достижении брекпойнта нажимает F11 и оказываемся там. Если дальше этот код протрассировать, то дойдем до ExitProcess. А ExitProcess убивает все потоки и заканчивает процесс. Память, выделенная при запуске потока стартовым кодом потока (а его посмотреть также несложно, протрассировав __beginthreadex) остается неосвобожденной, так как нормального окончания потока по прямому (явный вызов_endthreadex) или косвенному (вызов _endthreadex в финишном коде потока после выхода на закрывающую фигурную скобку потоковой функции) не произошло.

PD>Вот и все.

Если по трассировать как происходит выход из второго потока, то вот тут (Microsoft Visual Studio 10.0\VC\crt\src\threadex.c: line 312) происходит вызов _endthreadex:
--> _endthreadex (
( (unsigned (__CLR_OR_STD_CALL *)(void *))(((_ptiddata)ptd)->_initaddr) )
( ((_ptiddata)ptd)->_initarg ) ) ;

Собственно мне непонятно каким может быть ещё более нормальный выход из потока ?
Re[4]: msvc 2010, rtti memory leak ?
От: stil.man  
Дата: 29.07.13 13:25
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, stil.man, Вы писали:


SM>>Те же самые утечки.


U>предположу, что утечки связаны не с механизмом запуска потоков, а с содержимым функции f

U>1) уберите доп. потоки, вызовите функцию f из main, проверьте утечки
U>2) уберите вызов typeid из f, выполните ее в другом потоке, проверьте утечки
U>если утечки в пункте 1) остались, то снова предположу, что связано это с вызовом typeid, ведь данная функция должна возвращать ссылку на typeinfo. время жизни этого объекта должно переживать приложение (в стандарте более точно описано как долго должна жить ссылка)

Вы невнимательно прочли первый пост, в нем ясно говорится что если ту же функцию вызвать из основного потока то утечки нет.
Кроме вывода typeid.name() в функции нет ничего, так что убирать там нечего. Так же очевидно, что содержимое утечки (<struct vvv1 >) явно указывает на то что утекла именно name()

время жизни этого объекта должно переживать приложение


С этим утверждением сложно согласится Хотя, возможно, некоторые приложения верят в жизнь после смерти
Re[3]: msvc 2010, rtti memory leak ?
От: Pavel Dvorkin Россия  
Дата: 29.07.13 13:29
Оценка:
Здравствуйте, stil.man, Вы писали:


SM>Если по трассировать как происходит выход из второго потока, то вот тут (Microsoft Visual Studio 10.0\VC\crt\src\threadex.c: line 312) происходит вызов _endthreadex:

-->> _endthreadex (
SM> ( (unsigned (__CLR_OR_STD_CALL *)(void *))(((_ptiddata)ptd)->_initaddr) )
SM> ( ((_ptiddata)ptd)->_initarg ) ) ;

SM>Собственно мне непонятно каким может быть ещё более нормальный выход из потока ?


main запускает второй поток, после чего main завершается и происходит выход в код, вызвавший main, а он вызывает ExitProcess, который убивает все потоки. Код выше не исполняется, так как поток помер.
With best regards
Pavel Dvorkin
Re[5]: msvc 2010, rtti memory leak ?
От: uzhas Ниоткуда  
Дата: 29.07.13 13:39
Оценка:
Здравствуйте, stil.man, Вы писали:

SM>Вы невнимательно прочли первый пост, в нем ясно говорится что если ту же функцию вызвать из основного потока то утечки нет.

действительно, невнимательно

SM>Кроме вывода typeid.name() в функции нет ничего, так что убирать там нечего. Так же очевидно, что содержимое утечки (<struct vvv1 >) явно указывает на то что утекла именно name()

собственно я предложил убрать вызовы typeid

SM>

время жизни этого объекта должно переживать приложение


SM>С этим утверждением сложно согласится Хотя, возможно, некоторые приложения верят в жизнь после смерти

ну тут я мог плохо сформулировал мысль
лучше дам ссылку:
http://stackoverflow.com/questions/7024818/whats-the-lifetime-of-the-object-returned-by-typeid-operator
Re[3]: msvc 2010, rtti memory leak ?
От: omgOnoz  
Дата: 30.07.13 12:48
Оценка:
Вижу дамп мемори лика, но не вижу того, что тредом должно быть выведено.
Re[6]: msvc 2010, rtti memory leak ?
От: stbzh  
Дата: 30.07.13 15:34
Оценка: 3 (1)
Здравствуйте, uzhas, Вы писали:
U>лучше дам ссылку:
U>http://stackoverflow.com/questions/7024818/whats-the-lifetime-of-the-object-returned-by-typeid-operator
пожалуй могу отослать чуть точнее (там два варианта пофикса, не считая обновления до 12 студии): http://stackoverflow.com/questions/8308671/memory-leaks-after-using-typeinfoname
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.