Поподает ко мне в руки здоровенный проект, который не компилируется из-за циклической зависимости(в таком вот виде и попадает). И что бы найти ее и поправить, у меня уходит много времени. Тут я понимаю, что делать этого хорошо я никак не умею, а хотелось бы выработать некую технику для упрощения работы.
Поделитесь опытом.
«Мы с тобой в чудеса не верим, Оттого их у нас не бывает…»
Здравствуйте, meerius, Вы писали:
M>Поподает ко мне в руки здоровенный проект, который не компилируется из-за циклической зависимости...
"Циклической зависимости" чего? Классов? Файлов? Модулей?
Здравствуйте, meerius, Вы писали:
M>Поподает ко мне в руки здоровенный проект, который не компилируется из-за циклической зависимости(в таком вот виде и попадает). И что бы найти ее и поправить, у меня уходит много времени. Тут я понимаю, что делать этого хорошо я никак не умею, а хотелось бы выработать некую технику для упрощения работы.
и я не понял, Попал в руки? Это как? а твои обязанности по отношению к нему? а разработчики доступны?
Здравствуйте, Сергей Мухин, Вы писали:
СМ>и я не понял, Попал в руки? Это как? а твои обязанности по отношению к нему? а разработчики доступны?
Специально сокротил что, бы подчеркнуть что история недоступна, тоесть с момента когда проект компилировался, до момента когда он перестал компилироваться не известо что сделали — разработчили недоступны, нет контроля версий. А вот цекличиская зависимость точно есть файлов, положим только одна, которую и нужно найти.
«Мы с тобой в чудеса не верим, Оттого их у нас не бывает…»
Здравствуйте, dilmah, Вы писали:
D>тут без контрамоции не обойтись
Был один мастер, делал это на раз. Сначала пытался распечатать все инклюды, потом переименовывал файл кокого-то хедера(на диске, чтобы он не был найден), не знаю, как он его уж там выбирал, компилировал, смотрел, опять переименовывал, раз два и все...
Мастера больше нет и лак для скрипки остался не раскрытым.
«Мы с тобой в чудеса не верим, Оттого их у нас не бывает…»
Здравствуйте, meerius, Вы писали:
M>Был один мастер, делал это на раз. Сначала пытался распечатать все инклюды, потом переименовывал файл кокого-то хедера(на диске, чтобы он не был найден), не знаю, как он его уж там выбирал, компилировал, смотрел, опять переименовывал, раз два и все... M>Мастера больше нет и лак для скрипки остался не раскрытым.
1. В компиляторе включить опцию — распечатывать инклуды в лог. VC /showIncludes, в свойствах проекта: C/C++ > Advanced > Show Includes
2. Если это не поможет в расследовании, то добавить в каждый хедер (скриптом, конечно, а не руками) такой гвард
// включаем проверку (в самом начале)#ifdef __REENTERED__MY_HEADER_H__
#error MyHeader.h included recursively!
#endif
#define __REENTERED__MY_HEADER_H__
// как обычно, include guard
//#pragma once // эту прагму надо убрать, чтобы не мешать компилятору в ловле#ifndef __INCLUDED__MY_HEADER_H__
#define __INCLUDED__MY_HEADER_H__
.....
.....
.....
#endif//__INCLUDED__MY_HEADER_H__// отключаем (в самом конце)#undef __REENTERED__MY_HEADER_H__
Здравствуйте, meerius, Вы писали:
M>Поподает ко мне в руки здоровенный проект, который не компилируется из-за циклической зависимости(в таком вот виде и попадает). И что бы найти ее и поправить, у меня уходит много времени. Тут я понимаю, что делать этого хорошо я никак не умею, а хотелось бы выработать некую технику для упрощения работы. M>Поделитесь опытом.
Ну как обычно, 2 варианта: 1-й, он же совместимый: разбить заголовок на объявления и декларацию, обычно хватает и не вызывает цикл
2-й: MSVC #pragma once помогает очень хорошо, лечит кривые зависимости, жутко вредит мультиплатформенности.
3-й вариант, "подумать" — не предлагаю.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Ops, Вы писали:
Ops>Ну как обычно, 2 варианта: 1-й, он же совместимый: разбить заголовок на объявления и декларацию, обычно хватает и не вызывает цикл Ops>2-й: MSVC #pragma once помогает очень хорошо, лечит кривые зависимости, жутко вредит мультиплатформенности.
Ну если у GCC warning unknown pragma это жуткий вред для мультиплатформенности — тогда да.
Защищать от множественного включения надо в 99% случаев. Никакие кривые зависимости это не лечит.
Собственно п.1 и п.2 решают совершенно разные задачи. Это не варианты.
Здравствуйте, meerius, Вы писали:
M>Поподает ко мне в руки здоровенный проект, который не компилируется из-за циклической зависимости(в таком вот виде и попадает). И что бы найти ее и поправить, у меня уходит много времени. Тут я понимаю, что делать этого хорошо я никак не умею, а хотелось бы выработать некую технику для упрощения работы. M>Поделитесь опытом.
чтобы этого не возникало нужно
1. писать в хидерах только то, что будет использовано в другом файле(файлах), а не в файле реализующем хидер. то есть хидер — это только обьявление экспортируемых обьектов.
2. инклудить в хидер только то, что используется для дефиниций внутри хидера. и ни в коем случае не инклудить то, что не используется в хидере, а в его реализующем файле.
3. инклудить в хидер напрямую те файлы, что содержат необходимые для его деклараций обьекты, не допуская варианта, типа косвенного инклуда, то есть какого-то "левого" хидера, куда тем или иным образом проинклуденные нужные вам файлы. с такими левыми хидерами вы натаскиваете мусор в свой хидер.
4. если пред пункты не помогли. у вас плохое разбиение на модули и дефиниции в хидерах зависят друг от друга не в силу плохой структуры хидеров и инклудов, а плохого разбиения на модули. тут нужно просто слить друг с другом модули что друг от друга зависят. они явно должны быть обьеденены.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, meerius, Вы писали:
M>>Был один мастер, делал это на раз. Сначала пытался распечатать все инклюды, потом переименовывал файл кокого-то хедера(на диске, чтобы он не был найден), не знаю, как он его уж там выбирал, компилировал, смотрел, опять переименовывал, раз два и все... M>>Мастера больше нет и лак для скрипки остался не раскрытым.
К>1. В компиляторе включить опцию — распечатывать инклуды в лог. VC /showIncludes, в свойствах проекта: C/C++ > Advanced > Show Includes
Ну, вот, и я так же делаю.
К>
К>// включаем проверку (в самом начале)
К>#ifdef __REENTERED__MY_HEADER_H__
К>#error MyHeader.h included recursively!
К>#endif
К>#define __REENTERED__MY_HEADER_H__
К>
Это интерессно
«Мы с тобой в чудеса не верим, Оттого их у нас не бывает…»
Здравствуйте, meerius, Вы писали:
M>Согласен, только вопрос был не в этом... M>А как ты зависимость находешь, когда она уже есть?
не помню. возникают очень редко. и поскольку, в момент возникновения понять очень просто, что ты там проинклудил, и возникла зависимость, то найти проблему легко.
проблема в том, что какой-то хидер вдруг инклудит сам себя.
если понять какой хидер это делает, то находишь — как он это делает, то есть смотришь его инклуды. через какой-то из них и возникает инклуд самого себя.
обычно такая петля петля очень короткая, и она сразу определяется. просто представляя себе структуру программы.
серьезного то есть опыта у меня нет.
M>хотелось бы выработать некую технику для упрощения работы.
Загружаете утилиту Include File Dependencies Watcher.
Натравливаете ее на исходные файлы вашего проекта. Получаете график включения файлов.
Находите визуально циклы в этом графе.
Находите в цикле хэдер, который использует только ссылки и указатели.
Переносите из этого хэдера инклюды, вызывающие циклы в cpp файл.
Добавляете форвард декларации для убранных инклюдов.
Все.
Здравствуйте, meerius, Вы писали:
M>Здравствуйте, Ops, Вы писали: Ops>>3-й вариант, "подумать" — не предлагаю.
M>А я Вам очень даже предлагаю, но только после того, как перечитали топик еще раз.
А что не так? Если где-то встречается цикл, то это вполне локализуется, и вполне можно разорвать его, немного подумав. Еще вариант — некоторые компиляторы позволяют насильно внедрять во все юниты какой-нибудь хидер типа StdAfx, возможно он позволяет порвать зависимости.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.