Вчерая столкнулся вот с такой вот проблемой. Есть класс, в котором постоянно происходит чтение-запись реестра. Так вот где-то на пред. «итерации» разработки все было отлично (по другому никак – код тривиальный и уже отлаженный на сто раз). Но после того, как я добавил несколько функций-членов в класс (никак не связанных между собой ни переменными, ни вызовами) – этот метод вдруг перестал работать. Вот как все обстояло: в глоб. (назовём её так) функции создавался дескриптор ключа, а потом другая функция его использовала каждый раз. Так вот – при чтении одного параметра все было ок, а при чтении другого – нет. Win32 API функция RegQueryValueEx возвращала ок, а в в выходном значении (тип параметра) – была какая-то белиберда. Что я только не пробовал – перекомпоновка/перелопачивание не помогло; замена идентификаторов переменных – тоже. Спасло только постоянное открытие-закрытие дескриптора внутри ф-ии. Но ведь это же не избавляет меня от «недопонимания».
Вторая проблема: в моём классе были виртуальные функции, которые обрабатывали события от пользователя. Все было ок, а теперь одна из них вообще не вызывается. И это при том, что код предка класса и код этих функций я вообще никак не мог затронуть!!! Просто смешно.
Расскажу ещё: писал свой связанный список, возникла «плавающая» проблема: иногда указатель вдруг принимал непонятно откуда взявшееся «фантомное» значение! И это при том, что смена его идентификатора ничего также не дала. Какой-то странный баг. Проверил всё: от конструктора копирования до ветвлений
Есть и ещё одно: в дебаге передаю указатель на CDC в польз. Функцию. Все работате. Но как релиз – указателя как не бывало Ж-) Вероятность того, что это всё МОИ косяки – велика, ибо я не считаю себя даже программером «ниже среднего», но ведь 1 проблема явно не моя!
Ну а вот сегодня ещё!!! В той же самой проге, где все косячет (видно косячет все и сразу не просто так!) появилась ещё одна проблема. Функция, которая проверяет привелегии пользователя. Так вот – отдельно (в отдельном простеньком консольном приложении) все работает правильно, а здесь – метод выдает неверный результат!!! Могут ли все эти проблемы возникнуть из-за различных способов компоновки памяти (т.е. у меня много статических методов и переменных, а также виртуальных итд). Статика нужна для простоты работы с потоками, ведь мой класс больше является namespace-хранителем, т.е. создание множества инстанций не предполагается. Но делать все методы статическими как-то мне претит, использую reinterpret_cast.
Re: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.NET)
Если бы это был багланд дебилдер то я могбы поверить что это его косяки. Но в то что седьмой вижул так косячит я не верю. Скорее всего все эти проблемы из-за того что ты гдето пишешь за приделы массива, по не вернуму указателю итп. Тем болие что ты сам признаешся что знаешь С++ плохо. Остальные ошибки наведенные.
Воспользуйся BoundsChecker'ом быть может он поможет найти ошибку.
... << RSDN@Home 1.1.4 rev. 142 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, WolfHound, Вы писали:
WH> Но в то что седьмой вижул так косячит я не верю.
#include <stdio.h>
int main ()
{
char c[4];
c[0]='a';
c[1]='b';
c[2]='c';
c[3]='d';
printf ( "before: %c%c%c%c\n", c[0], c[1], c[2], c[3] );
for ( int j = 0; j < 2; j++ )
{
for ( int i = 0; i < 3; i++ )
{
c [ i ] = c [ i+1 ];
}
c [3] = 'x';
}
printf ( "after: %c%c%c%c\n", c[0], c[1], c[2], c[3] );
return 0;
}
/*
Roman Pshenichny Bug.
----------------
В debug все правильно, "cdxx". А в release "cxxx".
В VC6 в обоих случаях правильно. IC 7.1 тоже.
У кого какие мнения?
Sorry.
*/
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, WolfHound, Вы писали:
WH>Ты бы пост перечитал.
перечитал
Был еще такой случай "оптимизации": VS7.1 "оптимизировал" функцию случайного числа, так что она в некоторых случаях не выполнялась несколько раз подряд, и выдавала один и тот же результат.
Random random;
int i= random(); //random.operator()int j= random();
int k= random();
assert(i == j && k == j);
Симптомы были те же — неправильная работа только в release и только в VC7 .
Помогла замена внутреннего счетчика на volatile (может, этот бубен поможет и автору?).
Еще можно попробовать запустить на других компьютерах / OS, может это несервиспаченный Windows глючит? Попробовать откомпилировать на другом компиляторе (IC++, VC71). Попробовать отключить используемые библиотеки — может в них создаются потоки, которые гадят в память? И свои потоки тоже
А вообще, надо резать проект целиком до минимального кода... Правда, это может занять немало часов.
Правильно работающая программа — просто частный случай Undefined Behavior
Re[5]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, _Winnie, Вы писали:
_W>перечитал
О всех этих багах я знаю. Но в данном случае на лицо симптомы порчи памяти.
А автору может помоч только BoundsChecker или ему подобный софт. Хотя лично я даже не знаю как этой штукой пользоваться ибо у меня в этом небыло необходимости даже когда я работал на минном поле ака багланд дебилдер.
И учти
Вероятность того, что это всё МОИ косяки – велика, ибо я не считаю себя даже программером «ниже среднего»,
(С)Ahriman
А еще ошибки седьмого вижула можешь вспомнить? Кроме того что он что-то скомпилить не может? А про ошибки багланд дебилдера я и не только я могу долго расказывать.
Вобщем мое мнение: Вероятность наступить на ошибку кодогенерации в седьмом вижуле практически равна нулю. И учитывая не опытность автора вероятность порчи памяти около 100%.
ЗЫ Искать ошибки в компиляторе (особенно в мелкомягком) последнее дело. А вот проверить свою программу на вшивость...
... << RSDN@Home 1.1.4 rev. 142 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Ahriman, Вы писали:
WH>Если бы это был багланд дебилдер то я могбы поверить что это его косяки. Но в то что седьмой вижул так косячит я не верю. Скорее всего все эти проблемы из-за того что ты гдето пишешь за приделы массива, по не вернуму указателю итп. Тем болие что ты сам признаешся что знаешь С++ плохо. Остальные ошибки наведенные. WH>Воспользуйся BoundsChecker'ом быть может он поможет найти ошибку.
согласен, что VC не может так косячить, хотя он у меня и без сервис паков... Но я проверял и функциями _Crt*** ...
Re[5]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, _Winnie, Вы писали:
_W>Здравствуйте, WolfHound, Вы писали:
WH>>Ты бы пост перечитал. _W>перечитал _W>Был еще такой случай "оптимизации": VS7.1 "оптимизировал" функцию случайного числа, так что она в некоторых случаях не выполнялась несколько раз подряд, и выдавала один и тот же результат. _W>
_W>Симптомы были те же — неправильная работа только в release и только в VC7 . _W>Помогла замена внутреннего счетчика на volatile (может, этот бубен поможет и автору?).
хм.... я уже пробовал... думаю, что у меня скорее всего проблемы с reinterpret_cast, хотя указатель из стат. функции с его исп. получается вроде нормальный
Re[6]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, _Winnie, Вы писали:
_W>>перечитал WH>О всех этих багах я знаю. Но в данном случае на лицо симптомы порчи памяти. WH>А автору может помоч только BoundsChecker или ему подобный софт. Хотя лично я даже не знаю как этой штукой пользоваться ибо у меня в этом небыло необходимости даже когда я работал на минном поле ака багланд дебилдер.
WH>И учти WH>
WH>Вероятность того, что это всё МОИ косяки – велика, ибо я не считаю себя даже программером «ниже среднего»,
WH>(С)Ahriman
WH>А еще ошибки седьмого вижула можешь вспомнить? Кроме того что он что-то скомпилить не может? А про ошибки багланд дебилдера я и не только я могу долго расказывать.
WH>Вобщем мое мнение: Вероятность наступить на ошибку кодогенерации в седьмом вижуле практически равна нулю. И учитывая не опытность автора вероятность порчи памяти около 100%.
WH>ЗЫ Искать ошибки в компиляторе (особенно в мелкомягком) последнее дело. А вот проверить свою программу на вшивость...
но как??? пробовал уже все подряд. Перекомпоновкка/ переименование + проверка на порчу памяти (ф-ии _Crt****). Ед. всех этих тулзов у меня нет. Но ведь студия должна хотя бы ловить утечку памяти и перезапись (типа stack around variable corrupted А этого нет.
Re: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.NET)
Ahriman:
> после того, как я добавил несколько функций-членов в класс (никак не связанных между собой ни переменными, ни вызовами) – этот метод вдруг перестал работать. <...>
Комментируй код большими кусками. Когда при "отрезании" очередного куска проблема исчезнет, "включи" только что обнаруженный проблемный кусок, и "выключай" по частям теперь его, пока не доберешься до самого проблемного места. Альтернативный способ — проанализировать все фрагменты кода, осуществляющие запись в участки памяти, предшествующие "портящимся" переменным, на предмет записи за границы массивов и т.п.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.NET)
Здравствуйте, Ahriman, Вы писали:
A>Вчерая столкнулся вот с такой вот проблемой. Есть класс, в котором постоянно происходит чтение-запись реестра. Так вот где-то на пред. «итерации» разработки все было отлично (по другому никак – код тривиальный и уже отлаженный на сто раз). Но после того, как я добавил несколько функций-членов в класс (никак не связанных между собой ни переменными, ни вызовами) – этот метод вдруг перестал работать. Вот как все обстояло: в глоб. (назовём её так) функции создавался дескриптор ключа, а потом другая функция его использовала каждый раз. Так вот – при чтении одного параметра все было ок, а при чтении другого – нет. Win32 API функция RegQueryValueEx возвращала ок, а в в выходном значении (тип параметра) – была какая-то белиберда. Что я только не пробовал – перекомпоновка/перелопачивание не помогло; замена идентификаторов переменных – тоже. Спасло только постоянное открытие-закрытие дескриптора внутри ф-ии. Но ведь это же не избавляет меня от «недопонимания».
У меня такого рода проблемы были, когда я не инициализировал структуру, прежде чем ее куда-либо передавать (я передавал ее в WinAPI-функцию, и хотя в MSDN-е было написано, что ее не надо инициализировать, эта функция использовала первый член структуры, указывающий на ее размер). Так что тщательно проверьте, корректно ли вы инициализируете переменные, особенно агрегаты (классы, структуры, массивы).
Про проверку на выход за пределы массива в циклах я не говорю — надеюсь, сами знаете.
A>Ну а вот сегодня ещё!!! В той же самой проге, где все косячет (видно косячет все и сразу не просто так!) появилась ещё одна проблема. Функция, которая проверяет привелегии пользователя. Так вот – отдельно (в отдельном простеньком консольном приложении) все работает правильно, а здесь – метод выдает неверный результат!!! Могут ли все эти проблемы возникнуть из-за различных способов компоновки памяти (т.е. у меня много статических методов и переменных, а также виртуальных итд). Статика нужна для простоты работы с потоками, ведь мой класс больше является namespace-хранителем, т.е. создание множества инстанций не предполагается. Но делать все методы статическими как-то мне претит, использую reinterpret_cast.
Использование reinterpret_cast — признак очень плохого дизайна (не зря это ключевое слово такое неудобное и длинное). Здесь очень высока вероятности ошибки. У себя я использую такое преобразование только в самых экстремальных случаях (например, использование некоторых WinAPI-функций), и то создаю врапперы, которые осуществляют тщательную проверку. Возможно, вам стоит пересмотреть дизайн.
Re[2]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ahriman:
>> после того, как я добавил несколько функций-членов в класс (никак не связанных между собой ни переменными, ни вызовами) – этот метод вдруг перестал работать. <...>
ПК>Комментируй код большими кусками. Когда при "отрезании" очередного куска проблема исчезнет, "включи" только что обнаруженный проблемный кусок, и "выключай" по частям теперь его, пока не доберешься до самого проблемного места. Альтернативный способ — проанализировать все фрагменты кода, осуществляющие запись в участки памяти, предшествующие "портящимся" переменным, на предмет записи за границы массивов и т.п.
Спасибо за совет, но я уже все перепробовал. Я ведь даже если и писал, что не очень круто программлю (иначе не задавалбы таких глупых вопросов), но это-то я умею
Re[2]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
N>Использование reinterpret_cast — признак очень плохого дизайна (не зря это ключевое слово такое неудобное и длинное). Здесь очень высока вероятности ошибки. У себя я использую такое преобразование только в самых экстремальных случаях (например, использование некоторых WinAPI-функций), и то создаю врапперы, которые осуществляют тщательную проверку. Возможно, вам стоит пересмотреть дизайн.
хм... может и стоит, но косяк видимо даже не из-за этого. Я и без него пробовал, т.е. я менял "архитектуру" именно в этом плане, так как сразу же и стал туда "смотреть". Проблема ещё вот в чем — я наследуюсь от класса, а там куча кода, причем по-идее нормально работающего Придется все переписывать заново
Re[2]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ahriman:
>> после того, как я добавил несколько функций-членов в класс (никак не связанных между собой ни переменными, ни вызовами) – этот метод вдруг перестал работать. <...>
ПК>Комментируй код большими кусками. Когда при "отрезании" очередного куска проблема исчезнет, "включи" только что обнаруженный проблемный кусок, и "выключай" по частям теперь его, пока не доберешься до самого проблемного места. Альтернативный способ — проанализировать все фрагменты кода, осуществляющие запись в участки памяти, предшествующие "портящимся" переменным, на предмет записи за границы массивов и т.п.
Такая техника не поможет если Ahriman испортил память (в результате какой-нибудь ошибки).
Этими "включениями" и "выключениями" Вы просто переместите проявление дефекта из одного места в другое, или временно замаскируете его. Такие упражнения обычно заканчиваются крахом в самый неподходящий момент (прямо перед релизом).
Re: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.NET)
Эта вирт. функция, которую вызывает SCM при запуске сервиса!
void CMyContext2::OnServiceStart(){
HANDLE hWatchThread = CreateThread(NULL, 0, CheckForAccess,this, 0, 0);
}
так вот… при простом использовании этого кода (т.е. вставляем проверку на наличие пользователя в оболочку) – все работает (так и должно быть), но ЗДЕСЬ!!! Не пашет!!! Вот вам ещё и описание класса (который унаследован от RSDNова CServiceContext ) Так что там никаких глюков не должно быть:
Самое смешное, что до моей переустановки винды (у меня была Икс-ПИ рус без сервис паков )эта функция работала, а не работала другая (впрочем и она не пашет).
p.s. Пардон за стремное форматирование — монитор большой
Re[3]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, Ahriman, Вы писали:
A>хм... может и стоит, но косяк видимо даже не из-за этого. Я и без него пробовал, т.е. я менял "архитектуру" именно в этом плане, так как сразу же и стал туда "смотреть". Проблема ещё вот в чем — я наследуюсь от класса, а там куча кода, причем по-идее нормально работающего Придется все переписывать заново
Тогда возьми на вооружение принципы рефакторинга — это тебе поможет (если уж нет другого выхода, как все переписывать).
Re: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.NET)
От:
Аноним
Дата:
25.08.04 06:12
Оценка:
Здравствуйте, Ahriman
Если я правильно понял то ты пытаешся передавать адреса виртуальных функций(приведя их через reinterpret_cast) в API функции типа CreateThread(или аналоги типа beginthreadex), если так, то это верный способ создать глюкодром.
Re[3]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, _Winnie, Вы писали:
_W>Здравствуйте, WolfHound, Вы писали:
WH>> Но в то что седьмой вижул так косячит я не верю.
_W>[ccode] _W>#include <stdio.h>
_W>int main () _W>{ _W>char c[4]; _W>c[0]='a'; _W>c[1]='b'; _W>c[2]='c'; _W>c[3]='d';
_W>printf ( "before: %c%c%c%c\n", c[0], c[1], c[2], c[3] );
_W>for ( int j = 0; j < 2; j++ ) _W>{ _W>for ( int i = 0; i < 3; i++ ) _W>{ _W>c [ i ] = c [ i+1 ]; _W>} _W>c [3] = 'x'; _W>}
....
ГОСПОДА! Фишка действительно в памяти и ее защите в релизе... Попробуйте к сему коду поставить char c[5]; И все зафурычить как должно. Просто релиз смущает инструкция автора
c [ i ] = c [ i+1 ];
которая при значении i=3 не понимает "как человек взявший меня(VS7) такое пишет". Хотя действительно вроде операция безобидна.
Re[2]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Ahriman
А>Если я правильно понял то ты пытаешся передавать адреса виртуальных функций(приведя их через reinterpret_cast) в API функции типа CreateThread(или аналоги типа beginthreadex), если так, то это верный способ создать глюкодром.
ок, как мне быть без глюкодрома? Использовать везде статические члены? Не катит ... А как проверить, что этот реинтерпрет каст не работает? Кстати — и без него все точно так же выполняется, но видимо ...
Re[7]: Были ли у Вас такие проблемы (баги?) - MSVC++ 7.0 (.N
A>но как??? пробовал уже все подряд. Перекомпоновкка/ переименование + проверка на порчу памяти (ф-ии _Crt****). Ед. всех этих тулзов у меня нет. Но ведь студия должна хотя бы ловить утечку памяти и перезапись (типа stack around variable corrupted А этого нет.
студия не должна ловить утечку и перезапись памяти и не ловит, я видел только когда студия ругается на заюзывание непроиниченной переменной.
для поиска всех остальных багов есть софт специальный
Numega Bound Checker например
найди его поставь, вещь в быту программиста нужная, могу поспорить что он найдёт милион багов в твоей проге