C coding guidelines

T

Tech07

James said:
What it says is that "In a freestanding environment (in which C
program execution may take place without any benefit of an operating
system), the name and type of the function called at program startup
are implementation-defined."(5.1.2.1) but that otherwise, "The
function called at program startup is named main." (5.1.2.2.1p1). It
then imposes requirements on the values of the parameters of main().

I expected something like that. Good info.
Finally, it says
"If the return type of the main function is a type compatible with
int, a return from the initial call to the main function is
equivalent to calling the exit function with the value returned by
the main function as its argument;10) reaching the } that terminates
the main function returns a value of 0. If the return type is not
compatible with int, the termination status returned to the host
environment is unspecified." (5.1.2.2.3).

It goes into no more detail than that, about the code that an
implementation must generate that sets up the call to main(), and
reacts when that call returns. Therefore, the nature of such non-user
code is highly implementation-specific, and is best discussed in a
forum specializing in the particular implementation you're interested
in.

Oh! "Well, EXCUUUUSE ME!" ;)

People need to know the real truth, not just what the propoganda says. ;)
While such code is, in a very important sense, the real entry
point for the program, it is not the entry point from the point of
view of C programming.

Semantics. Colloquialism. So what. This isn't a fight or a war for the
ownership of the terminology "entry point". (?)
 
B

Bart

Well of course, the other poster was talking about Win32 programming.
Windows is largely C (probably entirely). You don't see any classes in the
Win32 API do you? Well, sure, now that there is C++ the startup code has to
address those requirements, but like I already noted, if you're just doing
C, the task of replacing the startup code (if you have such a bent) is a bit
easier.

I would find it easier to replace the lot and just be responsible for
everything. That's what I did years ago, until I started to make use
of first Win16, then Win32 + CRT.


I don't know what your point is in that passage, but I assure you that on
Windows, with the MS linker it's simple a switch (as in "light switch") to
send all startup code related to C library initialization to la la land. So
not complicated at all.

I'll take your word for it.
Now if you want to REPLACE that code, that gets a
bit more involved. I'll probably be building my code that way some day,
today though, I don't have all the info of what the startup code does: only
the basics. I think startup code should be provided in source code form.
Separate the proprietary OS code from the general language code.

That's the idea.

(Have to
stop here on that, or I'll start cursing the money-mongers).

Well maybe then you should go talk to Bill Gates and tell him to REMOVE it!
You go man!

From where?
Did you even go to the MSDN link I posted and read what was there?
Apparently not.

"...included in the C/C++ library code ... is the entry point
_DllMainCRTStartup..."

Sounds like if I wrote a DLL in assembler or my own private language,
the entry point wouldn't exist. Only the more general DllMain might be
recognised.
What language do you think Windows is written in? Visual Basic? Bzzzzt!
Wrong! Try again.

What's that got to do with what language I write *my* Dlls in? DLL
files are in PE-format, which is just a bunch of data structures. MS
specify a binary interface for calling functions in *their* DLL files,
but that's about it.

Oooops! I seemed to have missed "your claim". So, what are you "claiming"?- Hide quoted text -

That, um, DllMainCRTStartup is not an inherent part of any DLL file
(or even a stub for one), it's a specific of a C or C++
implementation.
 
T

Tech07

Richard said:
Mm-hmm. And when, in comp.lang.c, I say "entry point" I mean the entry
point into the C code. Context is all.

That's what I said (kinda). But you're still wrong. (LOL!).
 
T

Tech07

Bart said:
I would find it easier to replace the lot and just be responsible for
everything. That's what I did years ago, until I started to make use
of first Win16, then Win32 + CRT.




I'll take your word for it.


That's the idea.

(Have to

From where?

From the startup code! It's either in a DLL (if you only linked with the
import libraries) or linked to your executable if you statically linked to
the runtime libraries.
"...included in the C/C++ library code ... is the entry point
_DllMainCRTStartup..."

Sounds like if I wrote a DLL in assembler or my own private language,
the entry point wouldn't exist. Only the more general DllMain might be
recognised.

What do you think calls DLLMain?
What's that got to do with what language I write *my* Dlls in? DLL
files are in PE-format, which is just a bunch of data structures. MS
specify a binary interface for calling functions in *their* DLL files,
but that's about it.

What do you think calls DLLMain?
That, um, DllMainCRTStartup is not an inherent part of any DLL file
(or even a stub for one), it's a specific of a C or C++
implementation.

Well startup your debugger and trace through it. Then you will see the entry
point functions listed on that MSDN webpage I posted. (Are you "playing
dumb"? At this point, I'm done with this point!).
 
N

Nick Keighley

Eh? The return value is an int. What does that tell you? Nothing, except it
returns a value.

the key word in the above is "intent" not "short". I want to know
what the function is semantically intended to do. "Returns an int"
does not do that for me.
You need to know the significance of the return value, such as, "returns 1
to N if it works, 0 on failure".
yep.

Maybe some of this can be part of the description, but it doesn't hurt to
formally list the arguments (or parameters) and return value. Look at some
of the MSDN docs.

They're ok
 
N

Nick Keighley

I assume he wouldn't mind a good *long* summary if that is what it
takes ...



Of course! That can be as short as "returns success" or need a long
description (for example, if it is not clear what success means).


It does hurt, in my experience.  If you mandate comment headings like:

  Name: foo

  Arguments: bar - something
             baz - something
             bat - something

  Returns: something

then you'll never get people to document the functions properly, because
they spend themselves typing things like "len - the length". And half
the time the documentation will be outdated.

I've seen acres of stuff like this. Even when its well done (with the
caveat
that my fundamental belief that it is fundamentally broken),I still
think
it takes up too much space. The comments end upbeing bigger taht the
function.

/*
* numbers- an array of doubles
* count- the size of the array
*
* Returns: the average of the numbers
*
*/
double average (double numbers[], size_t count);

as opposed to
/* returns the average of the NUMBERS */

I don't touch that stuff. Look at some Unix section 2 and 3 man pages
-- that's the style I prefer. For example,

yawn. Unix good. MS bad.

   ...
   char *strcpy(char *dest, const char *src);
   ...
   The strcpy() function copies the string pointed to by src,
   including the terminating null byte ('\0'), to the buffer pointed
   to by dest. The strings may not overlap, and the destination string
   dest must be large enough to receive the copy.

The big difference here is that you get to form complete sentences --
keeps you somewhat intellectually honest -- and you can describe the
parameters in terms of how they work together. With the
list-of-arguments style, you have to pretend they have nothing to do
with each other (like a pointer to a buffer and its length).

fair point though I don't think the MSDN documentation fails to do
that
 
N

Nick Keighley

Why would you need to pretend the arguments have nothing to do with
one another simply because they are in a list? I have used the list
format with success and each argument was given a desciption in
complete sentences as you prefer and was described in in terms of
other arguments as required so I don't see how one is any better than
the other, simply personal preference. As far as the assertion that
one method or the other results in outdated comments I would suggest
that outdated comments are an issue no matter how you format the
comments, the format of the comments does not prevent them from being
updated laziness does.

In my experience prescriptive, heavy duty and above all REDUNDANT
documentation standards reduce the likelihood of keeping the comments
up to date. All documentation is a bit of an over-head; most
programmers
would rather write code. Why make the job harder when it can be made
easier.
 
B

Bart

Bart wrote:


From the startup code! It's either in a DLL (if you only linked with the
import libraries) or linked to your executable if you statically linked to
the runtime libraries.

Er, what runtime libraries?

You're still confusing the language of the OS which may or may not be
C, and the language of the DLL, which may or may not be C, and may or
may not have a runtime attached.

But if you want to think that C-Runtime initialisation code is used
when loading DLLs which are written in (for example) 100% assembler
and do not use the CRT, then that is up to you.

I happen to think that dllmaincrtstartup (excuse complete disregard
for correct case) is an artifact of C and C++ programming systems. And
one that even C and C++ programmers can completely ignore.
 
T

Tech07

Richard Heathfield said:
Who cares? The entry point is the point where control flow enters the
code. For a loop, that's normally the beginning of the loop (but it's
possible to mung this with goto). For a function, it's the beginning
of the function (hence the withdrawal of the 'entry' keyword which,
once upon a time, was going to allow a function to have multiple
entry points). For a suite of functions such as a library or a
program, it's the set of functions that are externally visible (i.e.
non-static) in the former case, and the function that is called by
the startup code in the latter.



Irrelevant. My DLLs don't even /have/ a DLLMain function,

Every DLL has a DLLMain function. It is automagically provided for you if
you don't write a specific one.
so what
makes you think it necessarily has anything to do with the entry
point into DLLs?

The REAL entry point function calls a function that calls DLLMain.
 
T

Tech07

Bart said:
Er, what runtime libraries?

C (or C++). Before you can use the C runtime library, it has to be
initialized. That's part of what the start up (WinMainCRTStartup or
_DLLMainCRTStartup) code does. Here are examples of those entry point
functions:

http://koders.com/c/fid93D487F174B6A014E72FF7723854024064FABFCB.aspx?s=winuser.h
http://koders.com/c/fidE0F9D8579445EAAF3DAAAA66D4CC57D5084335D9.aspx?s=winuser.h
You're still confusing the language of the OS which may or may not be
C, and the language of the DLL, which may or may not be C, and may or
may not have a runtime attached.

But if you want to think that C-Runtime initialisation code is used
when loading DLLs which are written in (for example) 100% assembler
and do not use the CRT, then that is up to you.

I happen to think that dllmaincrtstartup (excuse complete disregard
for correct case) is an artifact of C and C++ programming systems. And
one that even C and C++ programmers can completely ignore.

I would say that 1.) It is a good thing for all programmers to know about
how a program comes into existence, and that 2.) Knowing how to program for
the platform is more important than knowledge of a particular programming
language.
 
T

Tech07

Richard said:
I have a counter-example, and I can create as many more
counter-examples as I like.


The entry point(s) of a DLL must be a function (or functions) within
that DLL. If the DLL doesn't contain a DLLMain (and mine generally
don't), DLLMain can't be the entry point. If your claim is that the
real entry point is a function that calls DLLMain, and if no
functions within the DLL call DLLMain (which doesn't exist), then
according to you there is no entry point. And yet I can call
functions within the DLL.

It doesn't matter what text is in your source file. What matters is what
exists after the compiler/linker get done with it.
 
B

Bart

Right. And after the compiler (not linker, obviously, because it's a
library) is done with it, it contains no functions whatsoever with
the name DLLMain or anything like that name.

Why no linker? It's possible for a single library to consist of
several modules. And even with one it may be necessary to convert from
object file format.
 
J

jameskuyper

Bart said:
Why no linker? It's possible for a single library to consist of
several modules. And even with one it may be necessary to convert from
object file format.

The think which does that isn't a linker, it's an archiver - it
doesn't link the modules together; all it does is stuff them into the
library. The one I'm most familiar with is called 'ar'.
 
T

Tech07

Richard said:
Actually, I think it /does/ matter in the sense that the true entry
point into source code is a part of the source code. Nevertheless,
for *your* argument it *does* matter what is in the generated DLL
itself. Recognising this, I posted the output of strings(1) on the
.dll file itself, in a reply some days ago which you should still be
able to find, upthread. It contains no DLLMain.


Right. And after the compiler (not linker, obviously, because it's a
library) is done with it, it contains no functions whatsoever with
the name DLLMain or anything like that name.

Because the compiler included it for you and is using the default DLLMain.
 
J

jacob navia

Richard Heathfield a écrit :
No, the compiler didn't include it because it /isn't there/.

Please do not go on spewing nonsense and read the documentation.

All dlls have an entry point that is called at dll load time

This entry point function is called also when a thread starts or stops
and when the dll is unloaded.

The entry point of the dll is written into the executable by the
linker, that writes the file that will be loaded in memory. In the
header of the dll file is the address of the entry point.
 
J

jacob navia

Richard Heathfield a écrit :
I can do better than that. I can read the DLL - either the source or
the object code.


So what?

The ascii character string "Dllmain" will never appear. The linker
just writes in the header file the address of the Dllmain function
and the loader will load it. There is no "dllmain" character string
anywhere.

As you (may) know, executable code has no ascii strings that
give the name of the code you are running. The fact that you
can read the whole dll without finding the "dllmain" character
string doesn't mean the dllmain function is not there.

If I define in C:

static foo(void) { return 42;}

the name "foo" may very well NEVER appear in the executable.
It is there nonetheless!

This is so elemntary, and that I need to explain it to you
shows just your bad faith!

I think you may be talking about point of call, not
the entry point.

No, not "point of call". ENTRY POINT i.e. the address that
contains the executable code that will be executed when the
dll loads!
The entry point to a DLL is necessarily part of the
DLL.

GREAT. A correct sentence at last.
This DLL has no DLLMain.

The fact that you do not find any "dllmain" character
string doesn't mean the function is not there!

Therefore, DLLMain cannot be the entry
point to this DLL.
Faulty logic!
 
J

jacob navia

Richard Heathfield a écrit :
So we obviously disagree over the meaning of the term "entry point".
I'm using it to describe the point (or points) at which control flow
enters user code.


Fine. Then, as you (may) know, all dlls have
a point where control enters user code for the first time.

Got it?

This is the dllmain function!
For normal C programs, that's main(), and the
details of the C runtime are implementation-dependent and utterly
irrelevant. The claim was made that, for Win32 DLLs, it's DllMain (or
some case variant thereof).
Correct.

This is clearly not true for the DLL I
have in front of me (or any of its many brethren and sethren).

<snip>


Sorry but your dll (if it is one) has a file header, and in that
file header you will find the address of the dllmain function.

You keep trying to hide the fact that you are completely wrong.
The dll file header is standard win32, or win64. There you find
the address of the dllmain function!

How can you say its not there? You did a dll without header?

It is incredible how obtuse you can become when you are wrong!
 
J

jacob navia

Richard Heathfield a écrit :
A DLL can contain many functions. In some DLLs, there is a DllMain
function which acts as the entry point. In others, there is not.

This is what you refuse to understand Mr Heathfield.

ALL dlls will be called BY THE LOADER before the program starts.

This is NOT a call y your user code, it is a call by the
operating system and you can't do anything to avoid it.

This call will be done to a special entry point called DllMain
in the literature but can be actually any function that is
defined as entry point by the user.

The loader finds the address to call by looking at the header
of the dll. For instance, in the dll you sent me, the header
has the entry point field with a value of 0x1220 (4640 decimal)

This means that the loader will call the address:

DLL load point + 4640.

This is the address of the DllMain procedure. Note that this
address will change, depending on the address the dll itself
is loaded.

This call has standard arguments, described in the documentation.
It will receive those argumùents that allow it to see WHY it was called.

There are 4 calls to the entry point of the dll:
1) Before starting the program. Here the dll can use this occasion
to initilize stuff
2) When a new thread is started. Here the dll can initilize things in
a per thread basis
3) When a thread ends. Here you can do the opposite of what you
did at (2).
4) Just before when the program ends. Here you do the opposite as (1).

In
such DLLs, any one of the functions within the DLL (that is not
static) may be used first (except when there are internal
programmer-specified constraints that are not relevant here - a point
that is a side issue but upon which I will expand if required).

This is correct, but has nothing to do with the calls
done not by your code but by the code of the operating
system (the system program loader)
Here's an example of how a DLL can have multiple entry points:

#include "dlldemo.h" /* I posted source for this, upthread */
#include <stdio.h>

int main(void)
{
int i = foo(6); /* I posted source for foo(), upthread */
printf("%d\n", i);
return 0;
}

Prints 3 and a newline. Clearly, the entry point for the DLL is foo()
on this occasion.

You are right that here the entry point is foo(). But, that has
nothing to dow with the entry point OF THE DLL.
On no occasion was any DllMain function called. Neither did such a
function exist.

The call to the entry point is transparent to you. Since you did NOT
define an entry point, the compiler supplied you automatically
an entry point function that returns always TRUE and does nothing.

Then, you do not see it.

You can convince yourself of that by making a DllMain function
that always returns ZERO. You will see that the system will
refuse to load your dll!
Here's the DLL binary (assuming my Web server is up - if not, just say
and I'll fix it):

http://www.cpax.org.uk/scratch/dlldemo.dll

and here's the import library:

http://www.cpax.org.uk/scratch/dlldemo.lib

In case you find them useful, here are the sources:

http://www.cpax.org.uk/scratch/dlldemo.c
http://www.cpax.org.uk/scratch/dlldemo.h
http://www.cpax.org.uk/scratch/dlldemo.def


No. If I'm wrong, I'd like to find out, please. But so far it has not
been shown that I'm wrong.

I use pedump.exe to dump dlls. Your dll has an entry point of
0x1220
Even if it's there, for which I can find no evidence, it still isn't
the entry point into user code.


Show me.


Look. One way to cinvince yourself that dllmain is called
before your program starts is to use the debugger

(1) Write a DllMain function
(2) make it to write
printf("hello world from the dll\n"
when it receives the message DLL_PROCCESS_ATTACH
(3) print as first line in your main() procedure
printf("hello world from main\n");

You should see first the message from the dll. Do not
forget to start the program from a console window.

Here is the code that you can cut/paste to do that:

int WINAPI LibMain(HINSTANCE hDLLInst, DWORD Reason, LPVOID Reserved)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
printf("hello world from my dll!\n");
break;
case DLL_PROCESS_DETACH:
printf("The program is going to stop\n");
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
// Note that if you return zero, the progarm will not start
}


Note that I did not call the entry point DllMain but LibMain,
just to prove you that the name is USER DEFINED.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top