Здравствуйте, есть такой вопрос. Есть допустим си программа, в которой реализован рекурсивный обход каталогов. В рекурсивном обходе каталогов вызывается две функции, в которых происходит какое-то действие. Я значит запускаю программу в оле, на какой-то итерации обхода каталогов у меня происходит эксепшен. stack overflow. Ага, что-то срет в стек. Я переписываю функционал на си с асма. В асме у меня была подобная проблема. Там в стек срала wsprintf, которая за собой не подчищает стек. Так я там вручную делал так: stdcall [wsprintfA],[hBuffer],strSQL3,[strFunc],[.indexDLL] add esp,0x10 ага-ага, тут все ясно, но как такое сделать в си? Да и вообще глобально бы хотелось узнать об инструментах, которые отлавливают утечки памяти и не завязаны на VS. Я юзаю VS компилятор, но не собираюсь юзать саму VS. PS: вопрос в большинстве своем не о add esp,0x10, а скорее о инструменте, с помощью которого можно было бы эффективно находить утечки памяти.
Чтобы вручную не чистить стек, нужно обьявить соответствующий протитип: wsprintfA proto C Msg:PSTR.. Есть инструменты чтобы отслеживать утечки памяти хипа, но ошибки в алгоритмах они не находят.
в си wsprintf неспособна срать, так как компилятор сам добавляет add esp, 0x10. а так воспользуйтесь <crtdbg.h>. чтобы не пользоваться некошерной VS IDE, посмотрите на _CrtSetReportMode
Вы объявление wsprintf в заголовочном файле смотрели, прежде чем делать такие заявления? Или думаете что инструменты разработки идиоты пишут? Насчёт утечек памяти. В линукс есть valgrind. В винде студия тоже умеет кое-что - http://msdn.microsoft.com/en-us/library/e5ewb1h3%28v=vs.80%29.aspx. Даже кликом по строке в Output можно перейти на строку в исходнике, один минус, работает только для malloc. Есть отличная бесплатная библиотека "vld", которая и за new тоже следит.
common_up 1) Рекурсия и stack overlfow - прямо не верится - это сарказм 2) Приведение типов , или вызов по другому указателю, точнее тип указателя .. как то так.
у вспринтф ограничения в форматируемом буфере, и таки вроде как 1024 байтами... мсдн намекает на это...
Чёта стэк и хип не разные ли весчи? Тут имхо касяг в логике раз эксепшн stack overflow и это имхо не есть утечко.
а причем тут куча когда ты передаешь адрес стекового буфера? функция с переменным числом аргументов в любом случае чистит за собой, могу предположить лишь то что тем или иным образом указатель сдвигается, что в результате приводит к переполнению. включи секьюрити куки и смотри
sn0w Ф-ия с переменным числом аргументов как раз за собой не чистит стек. Это должна сделать вызывающая ф-ия, т.к. только она знает, сколько аргументов было реально передано.
Mika0x65 Нет смысла в функции, которая в рантайме не может определить, сколько ей передано аргументов. Поэтому вызванная функция также всегда знает, сколько ей передано аргументов. Проблема в отсутствии удобной аппаратной поддержки для очистки стека от буфера переменного размера на выходе из функции. Для статического числа аргументов есть retn n, а вот чего-то вроде retn ecx нету. Поэтому проще сделать add esp,n вне ф-ии, чем pop ecx, add esp,n, jmp ecx внутри.
l_inc На этапе компиляции не знает, если ф-ия будет помещена в библиотеку и доступна для внешних вызовов. Если смотреть со "статической" точки зрения. Можно сделать самомодифицирущийся код, например. Но тогда секция кода должна быть доступной для записи. Ну или pop ecx/add esp, n/jmp ecx, но тогда надо обязать пользователя передавать число аргументов или считать их в процессе исполнения.
Mika0x65 А какое это имеет значение? Важно, что происходит в рантайме. Это настолько плохое решение, что я его решил не упоминать в #11. Это в любом случае обязательно, т.к. должны быть обработаны все переданные аргументы.
Вот, например, там ограничение по времени использования, но по прошествии срока все равно работает. ЗЫ ну и подгрузить символы забывать не стоит ))
l_inc Насколько я помню, не обязательно, можно написать ф-ию с переменным числом параметров и не обрабатывать все элементы.
Mika0x65 Можно, конечно. Но, как я уже написал, "нет смысла в функции, которая в рантайме не может определить, сколько ей передано аргументов". Поэтому, если, скажем, printf вызывается, как printf("%d\r\n", a, b);, то это, наиболее вероятно, ошибка программиста, которая сравнительно гораздо легче обнаруживается в том случае, если вытирает за собой как раз вызываемая функция. А так компилятор вставит зачистку от трёх аргументов, и баг, в результате которого выводится одно значение вместо двух, может просуществовать гораздо дольше.
l_inc Логично, но в некотором смысле "ужесточние" функционала. Логика ф-ии может зависеть от самих аргументов, вовсе не обязательно использовать все аргументы. Не printf'ом единым же. Получается, надо либо обязать программиста передавать число аргументов, скажем, первым аргументом (кстати, я так когда-то делал) и потом от него плясать. В чем, в общем-то, нет ничего ужасного.