* 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:
parent
79b4d1beb0
commit
895ece0124
|
@ -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.
|
||||
|
|
|
@ -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, &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 *) &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>
|
||||
|
||||
|
|
Loading…
Reference in New Issue