473,401 Members | 2,146 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,401 software developers and data experts.

Questions regarding cyclic header dependency

Hi,

Is there any tools that could report where cyclic header dependency
happens? this would be useful when working with a large project where
tens or hundreds of headers files may form complex inclusion
relationships.

Another question I have is how to solve this dependency when "typedef"
is used. usually we can use forward declaration like "struc A; " to
solve references like "struct A* p". But in many places we have
"typedef struct A A_t;"in one header file, then how to solve references
like "A_t* p" in another header without including the first header?

Any hint in appreciated!

Jeremy

Apr 21 '06 #1
3 2711
fc****@gmail.com schrieb:
Hi,

Is there any tools that could report where cyclic header dependency
happens?
If you use header guards, then your compiler will refuse to compile
"cyclic" include dependencies that do not work. This helps you to
avoid such include dependencies early.
Tools such as PCLint might be able to help you but essentially it
is "do not get bitten in the first place".
If you are unlucky and inherited code that does not follow this
simple guideline, then start by inserting header guards header
by header and make sure the whole thing still does compile.
If you encounter cyclic dependencies, then resolve them by isolating
the common parts necessary for all headers in one separate header.
This can be done iteratively, if necessary.
this would be useful when working with a large project where
tens or hundreds of headers files may form complex inclusion
relationships.
If these relationships are not messed up in the first place:
No, I don't think so.
Only include what you need. As long as your compiler does not
run into numerical limits, everything is fine.

Another question I have is how to solve this dependency when "typedef"
is used. usually we can use forward declaration like "struc A; " to
solve references like "struct A* p". But in many places we have
"typedef struct A A_t;"in one header file, then how to solve references
like "A_t* p" in another header without including the first header?


Not at all.
If you want A_t, then include the first header -- it is the provider
of the typedef and should be the only provider.
Even if your compiler allows multiple identical typedefs, they are
still not standard C and can lead to trouble later on. As you talk
about large projects, you probably will have to port or migrate them
sooner or later -- this necessitates the usage of standard C wherever
possible.
If you want to communicate that A_t is in truth struct A and every
part of your program can alternatively use struct A, then A_t is
unnecessary.
With the exception of function pointer types, typedefs should not
be used to make typing a typename shorter but in order to express
a role the typedef fills.
A good article about typedefs from Chris Torek:
<dr*********@news4.newsguy.com>
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Apr 21 '06 #2

Michael Mair wrote:
fc****@gmail.com schrieb:
Hi,

Is there any tools that could report where cyclic header dependency
happens?
If you use header guards, then your compiler will refuse to compile
"cyclic" include dependencies that do not work. This helps you to
avoid such include dependencies early.
Tools such as PCLint might be able to help you but essentially it
is "do not get bitten in the first place".
If you are unlucky and inherited code that does not follow this
simple guideline, then start by inserting header guards header
by header and make sure the whole thing still does compile.
If you encounter cyclic dependencies, then resolve them by isolating
the common parts necessary for all headers in one separate header.
This can be done iteratively, if necessary.

header guards are always used. and compiler gives the error but still
this is very hard to figure out where it happens, since the C file may
contain a bunch of header files and each of them could have several
layers of inclusion themselves. I used another lint tool but and the
error message is not very helpful.
this would be useful when working with a large project where
tens or hundreds of headers files may form complex inclusion
relationships.


If these relationships are not messed up in the first place:
No, I don't think so.
Only include what you need. As long as your compiler does not
run into numerical limits, everything is fine.

when inheriting code from other people in a large project, people may
not just include what's really necessary. Later comers can run into my
situation even if they include what is necessary. when you have 5-6
levels of inclusion, you have no idea where the real problem is.
Another question I have is how to solve this dependency when "typedef"
is used. usually we can use forward declaration like "struc A; " to
solve references like "struct A* p". But in many places we have
"typedef struct A A_t;"in one header file, then how to solve references
like "A_t* p" in another header without including the first header?
Not at all.
If you want A_t, then include the first header -- it is the provider
of the typedef and should be the only provider.


I can't agree.
One rule I got from people was that whenever you are only referencing a
type name insead of its size, use forward declaration, not the header
file where the type is defined. This can effectively reduce possible
header coupling. But this seems not possible when typedef is widely
used.
Even if your compiler allows multiple identical typedefs, they are
still not standard C and can lead to trouble later on. As you talk
about large projects, you probably will have to port or migrate them
sooner or later -- this necessitates the usage of standard C wherever
possible.
If you want to communicate that A_t is in truth struct A and every
part of your program can alternatively use struct A, then A_t is
unnecessary.
With the exception of function pointer types, typedefs should not
be used to make typing a typename shorter but in order to express
a role the typedef fills.
My impression is that this kind of typedefs are widely used in
commercial production code.
A good article about typedefs from Chris Torek:
<dr*********@news4.newsguy.com>


Thanks for the info. I will try to find it.

Jeremy
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.


Apr 22 '06 #3
Jeremy schrieb:
Michael Mair wrote:
fc****@gmail.com schrieb:
Is there any tools that could report where cyclic header dependency
happens?


If you use header guards, then your compiler will refuse to compile
"cyclic" include dependencies that do not work. This helps you to
avoid such include dependencies early.
Tools such as PCLint might be able to help you but essentially it
is "do not get bitten in the first place".
If you are unlucky and inherited code that does not follow this
simple guideline, then start by inserting header guards header
by header and make sure the whole thing still does compile.
If you encounter cyclic dependencies, then resolve them by isolating
the common parts necessary for all headers in one separate header.
This can be done iteratively, if necessary.


header guards are always used. and compiler gives the error but still
this is very hard to figure out where it happens, since the C file may
contain a bunch of header files and each of them could have several
layers of inclusion themselves. I used another lint tool but and the
error message is not very helpful.


Most compilers offer you output of the preprocessed code,
sometimes complete with #line and #file directives; some even
offer to not descend into standard headers or headers included
using <>.
With this, you can often easier find the point where the error
occurs.

If you use version control of any kind, then you should be able
to pinpoint the change which made the whole thing uncompilable
and work from there.

this would be useful when working with a large project where
tens or hundreds of headers files may form complex inclusion
relationships.


If these relationships are not messed up in the first place:
No, I don't think so.
Only include what you need. As long as your compiler does not
run into numerical limits, everything is fine.


when inheriting code from other people in a large project, people may
not just include what's really necessary. Later comers can run into my
situation even if they include what is necessary. when you have 5-6
levels of inclusion, you have no idea where the real problem is.


If _much_ more is included than strictly necessary:
Use tools to throw out unnecessary includes from headers.
This makes it much easier to find errors.
I once inherited a 0.5 MLoc project with all the experts no
longer directly available. Cleaning up the headers in this
way helped a lot.

Another question I have is how to solve this dependency when "typedef"
is used. usually we can use forward declaration like "struc A; " to
solve references like "struct A* p". But in many places we have
"typedef struct A A_t;"in one header file, then how to solve references
like "A_t* p" in another header without including the first header?


Not at all.
If you want A_t, then include the first header -- it is the provider
of the typedef and should be the only provider.


I can't agree.
One rule I got from people was that whenever you are only referencing a
type name insead of its size, use forward declaration, not the header
file where the type is defined. This can effectively reduce possible
header coupling. But this seems not possible when typedef is widely
used.


I think you misunderstand:
,- someofmytypedefs.h --
#ifndef H_SOMEOFMYTYPEDEFS_H
#define H_SOMEOFMYTYPEDEFS_H

struct A;
.....

typedef struct A A_t;
.....
#endif
`---
,- a_stuff.h --
#ifndef H_A_STUFF_H
#define H_A_STUFF_H

#include "someofmytypedefs.h"

struct A {
....

};
#endif
`---
Even if your compiler allows multiple identical typedefs, they are
still not standard C and can lead to trouble later on. As you talk
about large projects, you probably will have to port or migrate them
sooner or later -- this necessitates the usage of standard C wherever
possible.
If you want to communicate that A_t is in truth struct A and every
part of your program can alternatively use struct A, then A_t is
unnecessary.
With the exception of function pointer types, typedefs should not
be used to make typing a typename shorter but in order to express
a role the typedef fills.


My impression is that this kind of typedefs are widely used in
commercial production code.


Yes. I thought you were talking about handwritten code.
For generated code, other rules apply; among other things, you
implicitly trust that constructs frowned on for handwritten code
are correct (by data flow and control flow analysis) and that
some uglies cannot be avoided without increasing the code
generation time and memory consumption.

FWIW, even production code generators can be convinced to not
emit typedefs of this kind; at least the good ones.

A good article about typedefs from Chris Torek:
<dr*********@news4.newsguy.com>


Thanks for the info. I will try to find it.


google groups still has it.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Apr 22 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Brian Sabolik | last post by:
I'm not sure if I've broken any Object Oriented rules or not, but ... I have projects in 2 different solutions that need to use each other's methods. Therefore I may have an "update" method in...
3
by: Dennis Lerche | last post by:
Hi I have a problem regarding cyclic dependency, yeahh I know bad design. But right at this moment I can't see how it should be redesigned to avoid this. The problem is that I just can't get it...
8
by: Christian Christmann | last post by:
Hi, I've a problem with including header files. class A requires header file of class B class B requires header file of class C class C requires header file of class A As can be seen the...
4
by: Alex Sedow | last post by:
For example, System.dll contains assembly reference to System.XML.dll, System.XML.dll refers to System.dll. Some another open projects contain cyclic assembly dependencies too. How C# compiler...
4
by: sakis.panou | last post by:
Hi all, Can anyone explain to me why the copy constructor of the COuterClass is getting called for this one? Let me start by saying I reckon this is seriously bad way of implementing anything of...
1
by: pallav | last post by:
I have two header files, circuit.h and latch.h that reference each other and are causing a cyclic dependency. latch.h file #include "circuit.h" typedef boost::shared_ptr<struct LatchLatchPtr;...
3
by: soup007 | last post by:
Hi, I am having some difficulties with cyclic dependency between two classes. Situation is something like following - ///A.h #include "B.h" class A { { int X; public:
6
by: scruggsy | last post by:
Hi, got a possibly stupid question. I have 2 header files each containing class definitions along the lines of: // Header1.h #pragma once #include "Header2.h" // for Class2 class ClassA { ...
11
by: sgurukrupagmailcom | last post by:
Hi, When searching for a solution to my problem I stumbled upon 'Curiously Recurring Template Pattern' see link. This is how the pattern looks: template < typename T > struct y { } ;
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.