* faq-programming.xml (faq.programming.64bitporting): New FAQ entry.

(faq.programming.objective-c): Include gcc4.
	(faq.programming.make-execvp): Drop text discouraging usage of -j.
	(faq.programming.undeclared-functions): Drop entry.
	(faq.programming.x86-assembly): Ditto.
	(faq.programming.djgpp): Ditto.
This commit is contained in:
Corinna Vinschen 2013-04-24 16:09:43 +00:00
parent 79b4d1beb0
commit 895ece0124
2 changed files with 165 additions and 42 deletions

View File

@ -1,4 +1,13 @@
2013-04-23 Corinna Vinschen <corinna@vinschen.de>
2013-04-24 Corinna Vinschen <corinna@vinschen.de>
* faq-programming.xml (faq.programming.64bitporting): New FAQ entry.
(faq.programming.objective-c): Include gcc4.
(faq.programming.make-execvp): Drop text discouraging usage of -j.
(faq.programming.undeclared-functions): Drop entry.
(faq.programming.x86-assembly): Ditto.
(faq.programming.djgpp): Ditto.
2013-04-24 Corinna Vinschen <corinna@vinschen.de>
* cygwinenv.sgml (cygwinenv-implemented-options): Change description
for winsymlink option to explain new implementation.

View File

@ -48,6 +48,158 @@ package. Or compile with the <literal>-s</literal> option to gcc.
</para>
</answer></qandaentry>
<qandaentry id="faq.programming.64bitporting">
<question><para>What do I have to look out for when porting applications to 64 bit Cygwin?</para></question>
<answer>
<para>The Cygwin x86_64 toolchain is using the
<ulink url="http://en.wikipedia.org/wiki/LLP64#64-bit_data_models">LP64</ulink>
data model. That means, in contrast to Windows, which uses an
<ulink url="http://en.wikipedia.org/wiki/LLP64#64-bit_data_models">LLP64</ulink>
data model, sizeof(long) != sizeof(int), just as on Linux.</para>
<para>For comparison:</para>
<screen>
Cygwin Windows Cygwin
Linux x86_64 Linux
Windows x86_64
i686
sizeof(int) 4 4 4
sizeof(long) 4 4 8
sizeof(size_t) 4 8 8
sizeof(void*) 4 8 8
</screen>
<para>This difference can result in interesting problems, especially when
using Win32 functions, especially when using pointers to Windows
datatypes like LONG, ULONG, DWORD. Given that Windows is LLP64, all of
the aforementioned types are 4 byte in size, while `long' on 64 bit Cygwin
is 8 bytes.</para>
<para>Take the example ReadFile:</para>
<screen>
ReadFile (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
</screen>
<para>In the 32 bit Cygwin and Mingw environments, as well as in the 64 bit
Mingw environment, it is no problem to substitute DWORD with unsigned
long:</para>
<screen>
unsigned long number_of_bytes_read;
[...]
ReadFile (fhdl, buf, buflen, &amp;number_of_bytes_read, NULL);
</screen>
<para>However, in 64 bit Cygwin, using LP64, number_of_bytes_read is 8 bytes
in size. But since ReadFile expects a pointer to a 4 byte type, the function
will only change the lower 4 bytes of number_of_bytes_read on return, while
the content of the upper 4 bytes stays undefined.</para>
<para>Here are a few <emphasis>donts</emphasis> which should help porting
applications from the known ILP32 data model of 32 bit Cygwin, to the LP64
data model of 64 bit Cygwin. Note that these are not Cygwin-only problems.
Many Linux applications suffered the same somewhat liberal handling of
datatypes when the AMD64 CPU was new.</para>
<itemizedlist mark="bullet">
<listitem><para>
<emphasis>Don't</emphasis> mix up int and long in printf/scanf. This:
<screen>
int i; long l;
printf ("%d %ld\n", l, i);
</screen>
may not print what you think it should.
</para></listitem>
<listitem><para>
<emphasis>Don't</emphasis> mix int and long pointers.
<screen>
long *long_ptr = (long *) &amp;my_int; /* Uh oh! */
*long_ptr = 42;
</screen>
The assignment will write 8 bytes to the address of my_int. Since my_int
is only 4 bytes, <emphasis>something else</emphasis> gets randomly overwritten.
Finding this kind of bug is very hard, because you will often see a problem
which has no immediate connection to the actual bug.
</para></listitem>
<listitem><para>
<emphasis>Don't</emphasis> mix int and pointers at all! This will
<emphasis>not</emphasis> work as expected anymore:
<screen>
void *ptr;
printf ("Pointer value is %x\n", (int) ptr);
</screen>
The value printed by printf is missing the upper 4 bytes, so the printed
value is very likely wrong.
</para></listitem>
<listitem><para>
Along the same lines <emphasis>don't</emphasis> use the type int in
pointer arithmetic. Don't cast pointers to int, don't cast pointer
differences to int, and don't store pointer differences in an int type.
Use the types <literal>intptr_t</literal>, <literal>uintptr_t</literal>
and <literal>ptrdiff_t</literal> instead, they are designed for performing
pointer arithmetic.
</para></listitem>
<listitem><para>
<emphasis>Don't</emphasis> make blind assumptions about the size of a POSIX
type. For instance, <literal>time_t</literal> is 8 bytes on 64 bit Cygwin,
while it is (still, at the time of writing this) 4 bytes on 32 bit Cygwin,
since time_t is based on the type long.
</para></listitem>
<listitem><para>
<emphasis>Don't</emphasis> use functions returning pointers without declaration.
For instance
<screen>
printf ("Error message is: %s\n", strerror (errno));
</screen>
This code will <emphasis>crash</emphasis>, unless you included
<filename>string.h</filename>. The implicit rule in C is that an undeclared
function is of type int. But int is 4 byte and pointers are 8 byte, so the
string pointer given to printf is missing the upper 4 bytes.
</para></listitem>
<listitem><para>
<emphasis>Don't</emphasis> use C base types together with Win32 functions.
Keep in mind that DWORD, LONG, ULONG are *not* the same as long and unsigned
long. Try to use only Win32 datatypes in conjunction with Win32 API function
calls to avoid type problems. See the above ReadFile example.
</para></listitem>
<listitem><para>
<emphasis>Don't</emphasis> mix Windows dataypes with POSIX type-specific
MIN/MAX values.
<screen>
unsigned long l_max = ULONG_MAX; /* That's right. */
ULONG w32_biggest = ULONG_MAX; /* Hey, wait! What? */
ULONG w32_biggest = UINT_MAX; /* Ok, but borderline. */
</screen>
Again, keep in mind that ULONG (or DWORD) is <emphasis>not</emphasis> unsigned
long but rather unsigned int on 64 bit.
</para></listitem>
</itemizedlist>
</answer></qandaentry>
<qandaentry id="faq.programming.glibc">
<question><para>Where is glibc?</para></question>
<answer>
@ -62,7 +214,7 @@ would be difficult.
<question><para>Where is Objective C?</para></question>
<answer>
<para>Support for compiling Objective C is available in the <literal>gcc4-objc</literal>
<para>Support for compiling Objective C is available in the <literal>gcc{4}-objc</literal>
package; resulting binaries will depend on the <literal>libobjc2</literal>
package at runtime.
</para>
@ -72,10 +224,8 @@ package at runtime.
<question><para>Why does my make fail on Cygwin with an execvp error? </para></question>
<answer>
<para>First of all, if you are using <literal>make -j[N]</literal>, then stop. It doesn't
work well. Also beware of using non-portable shell features in your
Makefiles (see tips at <ulink
url="http://cygwin.com/faq/faq.using.html#faq.using.shell-scripts" />).
<para>Beware of using non-portable shell features in your Makefiles (see tips
at <ulink url="http://cygwin.com/faq/faq.using.html#faq.using.shell-scripts" />).
</para>
<para>Errors of <literal>make: execvp: /bin/sh: Illegal Argument</literal> or
<literal>make: execvp: /bin/sh: Argument list too long</literal> are often
@ -681,15 +831,6 @@ This is right <literal>gcc hello.cc -lstdc++</literal>.
use <literal>struct stat</literal>. It's 64 bit aware.</para>
</answer></qandaentry>
<qandaentry id="faq.programming.undeclared-functions">
<question><para>I use a function I know is in the API, but I still get a link error.</para></question>
<answer>
<para>The function probably isn't declared in the header files, or
the UNICODE stuff for it isn't filled in.
</para>
</answer></qandaentry>
<qandaentry id="faq.programming.libc">
<question><para>Can you make DLLs that are linked against libc ?</para></question>
<answer>
@ -758,17 +899,6 @@ data types, line numbers, local variables etc.
</para>
</answer></qandaentry>
<qandaentry id="faq.programming.x86-assembly">
<question><para>Where can I find info on x86 assembly?</para></question>
<answer>
<para>CPU reference manuals for Intel's current chips are available in
downloadable PDF form on Intel's web site:
</para>
<para><ulink url="http://developer.intel.com/">http://developer.intel.com/</ulink>
</para>
</answer></qandaentry>
<qandaentry id="faq.programming.make-scripts">
<question><para>Shell scripts aren't running properly from my makefiles?</para></question>
<answer>
@ -848,19 +978,3 @@ executable.</para></listitem>
linker flag.</para></listitem>
</orderedlist></listitem></orderedlist>
</answer></qandaentry>
<qandaentry id="faq.programming.djgpp">
<question><para>Why not use DJGPP ?</para></question>
<answer>
<para>DJGPP is a similar idea, but for DOS instead of Win32. DJGPP uses a
"DOS extender" to provide a more reasonable operating interface for its
applications. The Cygwin toolset doesn't have to do this since all of
the applications are native WIN32. Applications compiled with the
Cygwin tools can access the Win32 API functions, so you can write
programs which use the Windows GUI.
</para>
<para>You can get more info on DJGPP by following
<ulink url="http://www.delorie.com/">http://www.delorie.com/</ulink>.
</para></answer></qandaentry>