DJGPP Frequently-Asked Questions List

Edition 2.0, for DJGPP Version 2.0

February 1996

by Eli Zaretskii

This is the DJGPP Frequently-Asked Questions List.

Copyright (C) 1994, 1995, 1996 Eli Zaretskii

This is the second edition of the FAQ list, and is consistent with version 2.0 of DJGPP.

This FAQ list may be freely distributed with the DJGPP package or any part thereof, provided this copyright notice is left intact on all copies.

DJGPP FAQ List

In DJGPP (see DJGPP overview), a 32-bit compiler and programming environment originally written for Unix machines, meet a 16-bit MS-DOS operating system. Programmer who work in this environment have to master a large body of knowledge from both Unix and MS-DOS, especially if they want to use some advanced features, like interrupt handling, directly accessing peripheral devices, etc.

But because the DJGPP project is a product of a group of volunteers, there isn't always enough time (or patience, or money ;-) to produce documentation which will describe all the subtle features and pitfalls a user should know about. The documentation of DJGPP-specific utilities and issues is therefore minimal, leaving wide space for confusion, in newcomers and veterans alike, and making the DJGPP learning curve quite a steep one.

This FAQ list is an attempt to take the sting out of that learning curve, by supplying solutions for problems which are known to puzzle DJGPP users. (Another solution would be to pay to DJ Delorie and other people who developed DJGPP to produce more documentation ;-) .

This is Edition 2.0 of the FAQ, last updated 21 February 1996, for DJGPP Version 2.0.

The sources of the latest version of this FAQ list can always be found as faq200s.zip on SimTel mirrors. This includes the source file (written in Texinfo), and all the auxiliary tools required to produce the Info, plain-ASCII, HTML, and a few other versions of the FAQ list; the FAQ in all these formats is available in a separate ZIP archive as faq200b.zip on SimTel mirrors. Currently, this includes the Info version, the text (ASCII) version and an HTML version as a single large .htm file. More formats will be available as the tools for their generation are developed/tested.

You can browse the HTML version of this FAQ list on line at the DJ Delorie's Web server.

If you browse this FAQ at DJ Delorie's server now, you can get the source distribution of the FAQ right here. Also available from the DJ's server: FAQ in all the supported formats.

This FAQ was also translated into French.

The following master menu lists the major topics in this FAQ list, including all the indices.

| Previous | Next | Up |

1. If You Are In a Hurry

Q: Do you really mean I have to read this looongish FAQ list to get my answers?

Q: I have this problem which I absolutely MUST solve NOW! What do I do?


A : No, you don't need to read all of the FAQ unless you want to (although this is by all means recommended). The questions in this documents are listed, as much as possible, in the order they appear when one goes through getting DJGPP, installing it and using it. To quickly find an answer to your question, first look at the Table of Contents. If that doesn't help, try the indices at the end of this manual. You can either look up your question by program name, or by topic name. If you don't find anything appropriate, search this FAQ for words which are pertinent to your problem. For those in a real hurry, here are some pointers to the most important topics in this FAQ list:

| Previous | Next | Up |

2. What is DJGPP?

Q: What is DJGPP?


A : DJGPP is a port of GNU C/C++ compiler and development tools to 32-bit, protected-mode environment on Intel 32-bit CPUs running MS-DOS and compatible operating systems, by DJ Delorie and friends. Starting from v2.0, DJGPP programs do not need a separate extender program, only a DPMI host to run; DJGPP includes a free 32-bit DPMI server which allows for a 32-bit, 4 GByte flat address space and up to 256 MBytes of virtual memory, a compiler which produces 32-bit protected-mode code, and a suite of GNU development tools ported to MS-DOS. These provide for a development environment which specifically favors porting Unix programs, but are also suitable for writing new code. With a few exceptions (notably, the C++ class library), DJGPP is free which makes it ideal for developing free and commercial software alike. DJ Delorie is the developer and principal maintainer of DJGPP, but anyone is welcome and encouraged to contribute.

| Previous | Next | Up |

3. Hardware and Software Requirements

This chapter describes what are the hardware and software which will allow you to use DJGPP. Minimum, "reasonable" and optimal system configurations are listed.

| Previous | Next | Up | Top |

3.1 The minimum system requirements for using DJGPP

Q: What are the minimum system requirements for using DJGPP?

Q: Will DJGPP run on my brand-new Acme i986DX7/300 PC with a SCSI-III 10-Terabyte disk drive under MulticOS/42 v7.99 operating system?


A : DJGPP requires at least 386SX CPU and between 15 and 35 MB of free disk space (see more details on this below), including space for the software installation and some swap space. A minimum of 64K of system memory is enough for DJGPP to run with the CWSDPMI free DPMI host (most other DPMI hosts will require much more), but at least 2.5MB of free extended RAM is recommended for reasonably fast compilation of large source files (4MB for compiling large C++ programs); you might see painfully slow compiles for large sources, if you don't have at least that much. If your machine doesn't have a numeric co-processor, you will need to install an emulator to run floating-point code (DJGPP provides such an emulator) or link your applications with a special emulator library (also provided with DJGPP).

DJGPP will run under native DOS; any other operating system is OK if it includes a DPMI server. Environments known to run DJGPP besides native DOS: Windows 3.1, 3.11 DOS box, OS/2 (including Warp) DOS box, Windows 95/DOS 7, Novell NWDOS 7.x (but several people has found the DPMI services of NWDOS buggy, so they should probably be turned off and CWSDPMI used instead), and Linux dosemu environment.

| Previous | Next | Up | Top |

3.2 Does it really work under OS/2?

Q: You tell me it will work under OS/2, but I'm experiencing strange crashes after several compilations ...


A : There was a bug in DPMI server of the old OS/2 versions, which is triggered by spawning child processes (like GCC does when it invokes the various compiler passes). If you can't upgrade to a newer OS/2 version, like OS/2 Warp, switch to a real-mode gcc.exe (from v1.x archives).

| Previous | Next | Up | Top |

3.3 Will it work under Windows/NT?

Q: What about Windows NT?


A : Windows NT currently cannot spawn DPMI programs, so you should use real-mode gcc.exe (it is in the gcc272rm.zip archive) and a real-mode Make program (like the one in the gnuish/ directory on SimTel). Also, any DJGPP program which calls any function from the spawnXXX family to run another DJGPP program, won't run under NT.

| Previous | Next | Up | Top |

3.4 Can I run it on a 286?

Q: Why can't I run DJGPP on my 286? It has protected mode also...


A : True, but the protected mode isn't an issue here. Gcc doesn't care much about memory protection, but it does care to run on a 32-bit processor, which 286 isn't. A 386 or better CPU really is required.

| Previous | Next | Up | Top |

3.5 MS-Windows applications and DJGPP

Q: Can I write MS-Windows applications with DJGPP?


A : Currently, you can only run DJGPP programs under Windows as DOS apps (i.e. inside DOS Box). If you need to write true Windows apps, try using the RSX extender with EMX port of GCC and RSXWDK kit for Windows. You can get RSX by anonymous ftp. People who tried this, report that you must download and unzip the RSXWDK2 source archive, not only the binaries (otherwise you'll get General Protection Faults when you try to run DJGPP programs). If you cannot reach the above site (some people say that it has closed its anonymous access), try looking for RSXWDK on Cica mirrors.

Apart from RSXWDK, you will need windows.h header file. One place to find it is with the WINE distribution.

You will also need a resource compiler.

Another way to develop Windows applications is to use the Cygnus GCC/GPP port. This one's compatible with Win32, but requires you to comply with GNU Copyleft system.

A better (but harder) way would be to volunteer to add Windows support to DJGPP.

Note that, as of this writing, nobody has reported any first-hand experience of using RSXWDK with DJGPP v2.0; the above is based on user reports under v1.x. If you try RSXWDK with v2.0, please post a summary of your experience.

| Previous | Next | Up | Top |

3.6 What you should buy ...

Q: What is the optimal system configuration for running DJGPP?


A : Here is the description of your dream machine (at least for the next 6 months :-) :

| Previous | Next | Up | Top |

3.7 What most of us will actually buy ...

Q: OK, I don't have this much money. What is the reasonable configuration?


A : If you have the following machine, you should be able to stop worrying about memory and compilation performance: This will leave you with about 8 MBytes of free extended RAM. Note that the RAM disk must be 4 MBytes to hold the output of the preprocessor for some exceedingly large source files (notably, some GCC source files). If you don't have that much RAM to spare and still want to compile very large source files, either reduce the disk cache so you can give more to RAM disk, or point TMPDIR to your hard disk and make the disk cache larger, if you can.

| Previous | Up | Top |

3.8 How to configure your system for DJGPP?

Q: How do I configure my system to get optimal performance under DJGPP?


A : That depends on the amount of RAM you have installed in your machine. Below are some guidelines to help you.
  1. If you have 2 MBytes or less RAM installed: With this configuration, GCC will run out of free physical RAM and page when compiling almost any C program and all C++ programs. If you are serious about DJGPP development, you need to buy more RAM urgently.
  2. If you have 2-4 MBytes of RAM installed: With this configuration, GCC will still run out of free physical RAM and page when compiling large C programs and most C++ programs. Plan to buy more RAM as soon as you can.
  3. If you have 5-8 MBytes of RAM installed:
  4. If you have more than 8 MBytes of RAM:

| Previous | Next | Up |

4. Where and What to Download?

This chapter explains where and how can you get DJGPP, and recommends what parts of the archive should you download. Application of maintenance releases (aka patches) is also discussed.

| Previous | Next | Up | Top |

4.1 Where can I get DJGPP?

Q: Where can I get DJGPP?


A : Look on any SimTel mirror in the vendors/djgpp/ subdirectory.
The primary site in Detroit, Michigan, USA:
ftp.coast.net.

Here is a list of hosts by countries that offer mirror sites:
Canberra, Australia:
archie.au
Newcastle, Australia:
ftp.iniaccess.net.au
Aarshot, Belgium:
ftp.tornado.be
Brussels, Belgium:
ftp.linkline.be
Sao Paulo, Brazil:
ftp.unicamp.br
Edmonton, AB, Canada:
ftp.agt.net
Beijing, China:
ftp.pku.edu.cn
London, England:
src.doc.ic.ac.uk
Lancaster, England:
micros.hensa.ac.uk
Espoo, Finland:
ftp.funet.fi
Neuilly, France:
ftp.grolier.fr
Paris, France:
ftp.ibp.fr
Bochum, Germany:
ftp.ruhr-uni-bochum.de
Chemnitz, Germany:
ftp.uni-chemnitz.de
Mainz, Germany:
ftp.uni-mainz.de
Tuebingen, Germany:
ftp.uni-tuebingen.de
Paderborn, Germany:
ftp.uni-paderborn.de
Hong Kong:
ftp.cs.cuhk.hk
Hong Kong:
ftp.hkstar.com
Naples, Italy:
ftp.unina.it
Pisa, Italy:
cnuce-arch.cnr.it
Rome, Italy:
ftp.flashnet.it
Saitama, Japan:
ftp.saitama-u.ac.jp
Saitama, Japan:
ftp.riken.go.jp
Tokyo, Japan:
ftp.crl.go.jp
Seoul, Korea:
ftp.kornet.nm.kr
Seoul, Korea:
ftp.nowcom.co.kr
Seoul, Korea:
ftp.nuri.net
Lithuania:
ftp.omnitel.net
Utrecht, Netherlands:
ftp.nic.surfnet.nl
Wellington, New Zealand:
ftp.vuw.ac.nz
Bergen, Norway:
ftp.bitcon.no
Krakow, Poland:
ftp.cyf-kr.edu.pl
Poznan, Poland:
ftp.man.poznan.pl
Warsaw, Poland:
ftp.icm.edu.pl
Aveiro, Portugal:
ftp.ua.pt
Slovak Republic:
ftp.uakom.sk
Slovenia:
ftp.arnes.si
Johannesburg, South Africa:
ftp.is.co.za
Stellenbosch, South Africa:
ftp.sun.ac.za
Stockholm, Sweden:
ftp.sunet.se
Zurich, Switzerland:
ftp.switch.ch
Chung-Li, Taiwan:
ftp.ncu.edu.tw
Taipei, Taiwan:
nctuccca.edu.tw
Nonthaburi, Thailand:
ftp.nectec.or.th
Ankara, Turkey:
ftp.metu.edu.tr
Concord, CA, USA:
ftp.cdrom.com
Urbana, IL, USA:
uarchive.cso.uiuc.edu
Rochester, MI, USA:
OAK.Oakland.Edu
St. Louis, MO, USA:
wuarchive.wustl.edu
Norman, OK, USA:
ftp.uoknor.edu
Corvallis, OR, USA:
ftp.orst.edu
Salt Lake City, UT, USA:
ftp.pht.com
The latest official distribution archive is also available from the FTP server set up by DJ Delorie, but please use that site only if unable to connect to one of the SimTel mirrors above, because DJ's server works over a modem and can be easily overloaded, which will hurt the unique services that server does (like the gateway between the mailing list and the newsgroup, searching the mailing list archives, the on-line FAQ version, etc.).

Note that DJGPP was recently moved to the SimTel/vendors/ directory on most SimTel mirrors. This is because SimTel claims a compilation copyright on its collection, to prevent people from copying the CD-ROMs which are distributed by SimTel. The GNU GPL prohibits any restrictions, even on compilations. So, FSF asked for GNU and GNU-related files to be moved to a separate directory to keep people from accidentally thinking that their rights were being reduced.

| Previous | Next | Up | Top |

4.2 How do I download DJGPP?

Q: How do I download files from these sites?


A : FTP to the nearest site, log in as anonymous, give your full e-mail address as password, and chdir to the djgpp subdirectory (the exact path to it might be different on different mirrors, see the DJGPP archive path.) Then issue the binary command and download files you need (see the list of required files) with the get command.

| Previous | Next | Up | Top |

4.3 What if I don't know what FTP is?

Q: What is that FTP thing? I only use Mosaic for Internet access.


A : OK, here are some URLs for your Web browser: You can also convert any of the mirrors' addresses listed in the list of SimTel mirrors, above to a valid URL by prepending ftp:// to it. For example, here is the URL for FTP from the primary SimTel FTP site.

Gopher users can access SimTel files through a Gopher client.

For those of you who have only e-mail connection to the Internet, SimTel files may be also obtained by e-mail from various ftp-mail servers or through the BITNET/EARN file servers. For details send a message to the SimTel list server with this command in the message body:


      get simtel-mailserver.info

You can also get DJGPP from CD-ROM copies of SimTel collections. You can either request a CD-ROM by e-mail, or order the SimTel CD-ROM through a WWW FORMS Interface.

| Previous | Next | Up | Top |

4.4 What Files to Download?

Q: What's the minimum set of .zip files I need to download?


A : This depends on what you are planning to use DJGPP for.

| Previous | Next | Up | Top |

4.5 How much disk space will I need?

Q: Wow, that's a lot of files. How much disk storage will I need?


A : The following lists the approximate disk space required for several major configurations, and additional storage required for some optional packages (binary distributions only):

     Execution-only environment..................300 KBytes
     Developing C programs.......................10 MBytes
     Developing C++ programs.....................13 MBytes
     Developing Objective-C programs.............11.5 MBytes
     Additional storage for C Library sources....2.7 MBytes
     Additional storage for GDB..................1.1 MBytes
     Additional storage for Flex.................280 KBytes
     Additional storage for Bison................310 KBytes
     Additional storage for Diffutils............560 KBytes
     Additional storage for Make.................520 KBytes
     Additional storage for Patch................120 KBytes
     Additional storage for Sed..................73 KBytes
     Additional storage for Graphics libraries...2.8 MBytes

In addition to the space for installing the software, you will need some free disk space for the swap file. You should leave enough free disk space to make the total virtual memory at least 20 MBytes; that will be enough for most applications. Invoke the go32-v2.exe program without arguments to see how many DPMI memory and swap space can DJGPP applications use. Depending on your DPMI host, you might need to review its virtual memory settings in addition to leaving free disk space; CWSDPMI needs only the disk space.

| Previous | Up | Top |

4.6 Can I get away with less megabytes?

Q: The above table means that I need more than 15 MBytes for C/C++ development environment; that's about 7 1.44MB diskettes to hold the compressed archive!! Seems to me DJGPP is afflicted by the fatware disease...

Q: Pulling that much megabytes through the net from my overloaded SimTel mirror is almost impossible. Can't you prepare a ZIP archive which only includes stuff I can't do without?


A : There is a number of shareware/freeware programs floating around which allow to format DOS diskettes to almost twice their usual capacity, so you can use less floppies. One such program is 2M, available from SimTel mirrors as 2mNN.zip.

To make downloading DJGPP easier, download and compile the BatchFTP program. It allows you to submit a script of FTP commands and will repeatedly try to login into the FTP site you specify until the script is successfully completed. It is smart enough to understand the messages which the FTP server sends to you (like login refused etc.) and also is nice to the remote server by sleeping for some time between login attempts. BatchFTP is free software and can be found on many FTP sites.

BatchFTP is a Unix program; those who access the net from their PC (not by dialing into some Unix host), can use a nice FTP-automating utility called AutoWinNet (get the file autownNN.zip from your nearest SimTel mirror).

| Previous | Next | Up |

5. The DJGPP Documentation

This chapter explains where to find and how to read DJGPP documentation, and how to solve occasional problems with the docs system.

| Previous | Next | Up | Top |

5.1 Where are the documentation files?

Q: I don't see any documentation files...


A : The documentation files are in the info/ subdirectory of your main DJGPP installation directory. You will need a program to read these docs, which are hypertext structured files. You have several choices:
  1. Use the stand-alone Info reader.

    Get the file txi360b.zip, which includes INFO.EXE and its docs. Unzip it and run Info. It will bring up a (hopefully) self-explanatory online help system. Confused? Press ? to see the list of all Info commands. Still confused? Press h to have Info take you on a guided tour through its commands and features.

  2. Use the Info command of your favorite Emacs-like editor.

    If you use Emacs, you already know about Info. (What's that? You don't? Type C-h i and you will get the top-level menu of all the Info topics.)

| Previous | Next | Up | Top |

5.2 How to read the docs without Info?

Q: I'm too old/lazy/busy to learn yet another browser, and I despise uGNUsable programs like Emacs. How in the world can I read the DJGPP docs??


A : Info files are almost plain ASCII files, so you should be able to browse them with your favorite text file browser or editor. You will lose the hypertext structure and you might have hard time finding the next chapter (hint: look up the name of the Next node at the beginning of this node, then use the search commands of the browser, or the Grep program, to find that name), but other than that you will see all the text.

Anthony Appleyard has translated the Info files for GNU C/C++ Compiler (gcc.iNN) and GNU C Preprocessor (cpp.iNN) into ISO-8859 (aka plain ASCII), and Stephen Turnbull has made them available on his anonymous ftp and WWW server. You can get them as gcc.txt and preprocessor.txt by anonymous ftp; or get them with your Web browser.

You can also produce pure ASCII files yourself, if you have their Texinfo sources. These are usually called *.txi or *.tex and should be included with the source distribution of every package. To produce an ASCII file foo.txt from the Texinfo file foo.txi, invoke the Makeinfo program like this:


      makeinfo --no-split --no-headers --output foo.txt foo.txi

The Makeinfo program is part of the Texinfo distribution which is available in txi360b.zip.

| Previous | Next | Up | Top |

5.3 How to print the docs?

Q: I like my docs the old way: printed on paper, stacked near my workplace. How can I print the documentation files which come with DJGPP?


A : You will need to get and install a program called TeX or its work-alike, like LaTeX or emTeX. (They are NOT part of DJGPP.) Then run your TeX work-alike on the docs' source files (called *.txi or *.tex) which you get with every *s.zip file you download. You will get a .dvi file which you can print; or you can run a DVI-to-PostScript converter like DVIPS to produce a PostScript output. DVIPS is a free program; you can find it with your archie client.

DJGPP comes with a program called TEXI2PS which can convert *.txi files to a crude PostScript; try it if you don't care much about the appearance of the printed docs.

If TeX won't run, check that you have the file texinfo.tex which defines the TeX macros specific to Texinfo files. If you don't, get the GNU or DJGPP Texinfo distribution which includes that file.

Note that some docs files (notably, those for GCC) will produce voluminous print-outs. You have been warned!

| Previous | Next | Up | Top |

5.4 Where can I find docs in PostScript?

Q: I don't have all these fancy packages, and I don't have disk space to install them in the first place. Can't you guys just include with DJGPP a set of ready-to-print PostScript files?


A : They are very large and would eat up too much storage (much more than the fancy packages you don't want to install). Most of the people read the docs on-line and never print them anyway. Sorry.

However, some Good Samaritans from all across the Net have taken time and effort to produce the docs in PostScript format and made them available by anonymous ftp. The most full set of docs for the latest versions of GNU software is available in plain ASCII, zip and tar.gz format by anonymous ftp from phi.sinica.edu.tw; they are all for A4 paper. Other places to look for PostScript versions of GNU documentation are:

In European A4 format.
In US letter format.

Many GNU manuals in HTML (hypertext) format, suitable for reading with your Web browser can be viewed at the DJGPP Web site.

DJGPP includes a utility called TEXI2PS which converts the Texinfo source files to crude PostScript; try it.

| Previous | Next | Up | Top |

5.5 Some docs are nowhere to be found...

Q: I looked in my info/ subdirectory, but I can't find docs for some of the utilities, like Sed or Gprof.


A : Download the source archive (*s.zip) for that package and look inside it, usually in the directory called man or doc.

| Previous | Next | Up | Top |

5.6 What are these foo.1 files?

Q: Some docs files are called foo.1 or bar.man or baz.nroff, and they seem to be written in some weird format which is very difficult to read. How can I convert them to readable text files?


A : That weird format is the troff format which is used for writing Unix manual pages. The Unix command man converts them to formatted text files which are usually displayed with a program like more or less (and here less is considered to be more than more :-) ). The formatted file includes bold and underlined letters produced by over-typing using Backspace characters. To format these files, you can choose one of these methods:

No matter which of the above methods you choose, you will need some kind of browser which understands how to show bold and underlined letters instead of backspace-over-typed characters. I suggest to download a DOS port of GNU Less, which uses colors to show bold and underlined letters. Another possibility is to get the latest official GNU Less distribution which can be compiled out of the box with the Microsoft C compiler (but I didn't try to do so).

Another possibility to read formatted man pages would be with an Emacs editor, if you use one. Emacs has a special command to read man pages.

Beginning with version 3.6, the stand-alone Info program can also read man pages (it invokes a subsidiary program man to format them, then displays its output; see the file readme.dj in the DJGPP Texinfo distribution for more details on how to set this up). So if you have the DJGPP Texinfo distribution, you can read man pages with Info already; if not, just download Texinfo.

Note that, for GNU packages, the man pages aren't always updated on a regular basis. If you need more up-to-date information, see the Info files.

| Previous | Up | Top |

5.7 What if the docs don't say enough?

Q: OK, I've got the docs and have read it, but I still can't figure out some details.


A : Download the sources and look there, or ask on the net--either the DJGPP mailing list or an appropriate GNU Newsgroup.

| Previous | Next | Up |

6. When the Compiler (or Make, or Info, or ...) Crashes...

This chapter explains how to deal with certain problems which may prevent DJGPP programs from running on your machine. The first 7 items on the next menu describe specific problems; if yours doesn't go away with these techniques, read the description of the general debugging procedure.

| Previous | Next | Up | Top |

6.1 Buggy DPMI host can crash v2.x programs

Q: When I try to run Info, it crashes imediately...

Q: I cannot run v2.0 applications: they all hang or reboot my system, while v1.x apps run OK. Is this what v2.0 is all about--getting me out of the DJGPP community?


A : No, believe it or not, we don't want to oust you. Your problems might be caused by a buggy DPMI (see DOS Protected Mode Interface) host installed on your machine. One DPMI host which is particularly known to be a source of trouble is the DPMI server which comes with Novell NWDOS. Please see if v2.0 programs run when you disable DPMI services of your usual configuration (DJGPP will then use the CWSDPMI program supplied with DJGPP).

Another DPMI host which is known to cause problems in DJGPP is Quarterdeck's QDPMI which comes with QEMM 7.5. It was reported to cause Info and all DJGPP debuggers to crash. If you use QDPMI, upgrade to the version 7.53 or later (patches for that version are available from the Quarterdeck's ftp site), or disable QDPMI and use CWSDPMI.

| Previous | Next | Up | Top |

6.2 GCC can crash during optimization

Q: When I compile my program, the compiler crashes, but the problem seems to go away if I compile without optimization.


A : GCC 2.6.0 was known to have such bugs, especially when compiling C++ programs, but it can also happen for later versions. (This is usually a genuine GCC bug, not something special to DJGPP.) Upgrade to the latest version of GCC. If the problem won't go away, then narrow the offending code fragment using the #if 0 ... #endif paradigm. If this fragment includes an error, correct it and try again; if it is syntactically and semantically correct, then rewrite it as equivalent, but syntactically different one. You can also try to disable the strength-reduction optimizations of GCC by using the -fno-strength-reduce switch. GCC has a known bug in that type of optimizations; this bug raises its ugly head on rare occasions, but is notoriously hard to hunt when it does. (The stock v2.0 distribution should by default disable this kind of optimizations on the lib/specs file.) As an extreme measure, don't optimize at all, if that's the only way to make your program work.

Another reason for this could be some problem with your system hardware or the BIOS (like if you set an incorrect number of wait states when accessing memory). To check, try running the same compilation on another machine, or review your BIOS settings.

| Previous | Next | Up | Top |

6.3 What does "Fatal signal X" mean?

Q: I get "fatal signal 2" when I run GCC.

Q: GCC aborts with "Internal compiler error" when compiling a large C++ program.


A : When GCC reports a "signal", it really means that an error occurred trying to run the given program. The "signal" number is the DOS error code, and 2 means "file not found" (dig out your DOS reference for other error codes). This means GCC couldn't find some program it needs to run to compile your source. Check the COMPILER_PATH environment variable or what the COMPILER_PATH line in the DJGPP.ENV file says, and make sure they point to the directory where DJGPP programs reside. Also check that the named directory has all the required programs: cpp.exe, cc1.exe, cc1plus.exe, cxxfilt.exe, gasp.exe, as.exe, ld.exe, and (for Objective-C) cc1obj.exe. You can use the -v switch to GCC to see what programs it invokes.

The "Internal compiler error" message usually means a genuine bug in GCC (which should be reported to FSF), but it can also happen when GCC requests additional chunk of memory, but the DPMI server fails to allocate it because it exhausts available memory for its internal tables. CWSDPMI can fail like this if an application asks for a larger number of small memory chunks. You can enlarge the maximum space that CWSDPMI uses if you get a CWSDPMI heap-fix patch. You can also run stubedit on cc1plus.exe and enlarge its maximum stack size to 512K bytes (some people report that they needed to enlarge both the heap of CWSDPMI and the stack of the C++ compiler to make this problem go away).

For a program that you wrote, another work-around is to use an alternative algorithm for sbrk, by putting the following somewhere in your program:


       #include <crt0.h>
       int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;

| Previous | Next | Up | Top |

6.4 What does "Unknown filetype" mean?

Q: I get error messages saying "Unknown filetype" from GCC.

Q: Since a few days ago, whenever I try to run most of the DJGPP programs, they print a message "C:\DJGPP\BIN\prog.exe: not COFF" and just terminate. Help!!!


A : It might be that your STUBIFY.EXE are infected by a virus. (This is not a joke! It did happen to a few of us and can happen even to you.) As the DOS stub prepended to the DJGPP programs is very small, most viruses cannot attach themselves to it without overwriting the beginning of the DJGPP COFF image, therefore triggering this error from the code in the stub that loads the COFF image.

Another possible cause of the "Unknown filetype" message is that you mix v2.0 gcc.exe driver with cc1plus.exe, cc1.exe or other programs from an old v1.x distribution.

| Previous | Next | Up | Top |

6.5 You can't use QEMM auto/off mode with DJGPP

Q: Why do I get error message from CWSDPMI if I keep QEMM in auto/off mode and run DJGPP?


A : When QEMM is in auto/off mode and there isn't anything in the system that is using any of QEMM's features, the CPU remains in real mode. Normally, when CWSDPMI finds the CPU in real mode, it will try to use raw XMS services to access the extended memory. Unfortunately, when some program requests XMS services, it will cause QEMM to turn on. So if CWSDPMI tries to switch into protected mode, QEMM will trap it and give a protection violation warning. To avoid this unfortunate event (which requires a system reboot to fix), CWSDPMI first checks to see if enabling XMS caused the CPU to switch into v86 mode (meaning QEMM just turned on). If so, CWSDPMI gracefully exits after telling you it can't work in this set-up, like this:

      "Error: Using XMS switched the CPU into V86 mode."

All you have to do to work around this is force QEMM to be ON whenever you run DJGPP programs so that CWSDPMI will know how to work with it properly. To do this, just turn QEMM on before running any DJGPP program, with this command:


      c:\qemm\qemm on

(that assumes your QEMM directory is c:\qemm).

| Previous | Next | Up | Top |

6.6 Compiler hangs, but only when invoked from Make

Q: My compiles run OK from the command line, but hang when I invoke the compiler from Make.


A : Be sure you are invoking the correct Make program. Borland Make was reported to cause trouble when you invoke GCC with it. It might be that another program called Make is found earlier on your PATH than the Make which came with DJGPP.

If you use Make compiled under DJGPP v1.x, you will also experience all kinds of trouble when invoking programs compiled under DJGPP v2.0. That's because v1.x programs cannot spawn v2.0 programs directly (the v1.x program sees that the child is a DJGPP program and tries to call go32 to run it). The result usually will be that the child crashes. If that's your problem, be sure to upgrade your Make to the port distributed with v2. (Note that v2.x programs generally know how to spawn both v1.x and v2.x programs.)

Some users report that v1.x programs might sometimes hang or reboot the machine when invoked from v2.0 Make, if the Makefile calls the v1.x program by a name longer than the 8+3 DOS filename restriction. To work around, truncate the filename of that program in the Makefile.

| Previous | Next | Up | Top |

6.7 Info doesn't like some files

Q: When I run the Info browser, it tells me it cannot find the node "Top".


A : Check your installation of info files. The file DJGPP.ENV in the root of your DJGPP installation mentions the variable INFOPATH which should point to the directory where Info looks for its files. It must find there a file named dir, the file you are trying to read, and other files with .iNN or .NN extension, where NN is a number.

Assuming the above checks OK, and all the necessary info files are indeed installed in those directories (did you remember to give that -d switch to PKUNZIP?), it might be that some of the files were edited with a DOS-based editor, which converted the Newline characters to the CR/LF pairs. Some DOS ports of Info don't like this, because this invalidates the tag tables included with the files, which Info uses to quickly find the various nodes.

To solve the problem, upgrade to the latest versions of Info ported to DJGPP, which don't have this problem (beginning from version 3.6).

If you cannot upgrade for some reason, run DTOU.EXE on the offending files, it will strip the extra CR characters to make Info happy. DTOU is in your bin/ subdirectory of the main DJGPP directory.

| Previous | Next | Up | Top |

6.8 My problem isn't mentioned above!

Q: I've installed DJGPP just like explained in README.* files, but when I run gcc, my machine crashes/hangs/needs cold boot.

Q: When I compile my program, gcc says "Segmentation violation" and prints all kinds of funny numbers and registers.

Q: I get errors I can't figure out when I try to compile something.


A : Add the -v switch to the GCC command line and run it again. It will print all the subprograms (compiler passes) it is running. Then you can see which subprogram caused the error, or where does your machine crash. This might give you a hint on what's wrong.

| Previous | Next | Up | Top |

6.9 I can't keep up with the error messages

Q: I want to read all the error messages that GCC throws on me, but they are so many that I can't keep up. How can I redirect them to a file?

Q: When I add -v to the GCC command line, how can I put all the voluminous output into a file, so I don't miss anything when reporting a problem?

Q: I have this nifty graphics program which bombs from time to time, but the registers and traceback info is hidden by the graphics display. How can I see it?


A : There are several alternatives:
  1. You can use a shell smarter then COMMAND.COM, such as 4DOS, which knows how to redirect standard error stream to a file. 4DOS is shareware and can be found on SimTel.
  2. You can also run your program under any one of the programs which save the output of programs they spawn in a file. I suggest using a program called SCRIPT, which is similar to its Unix namesake. It has an advantage of saving everything which goes to screen and showing it on the screen at the same time. You can find SCRIPT on SimTel.
  3. Or you can use the REDIR program which comes with DJGPP. It also redirects standard output and/or standard error to a file, but you don't get a chance to look at the output while the program runs.

| Previous | Next | Up | Top |

6.10 How to search DJGPP archives for similar problems

Q: OK, I have all this voluminous output of gcc -v, but I still have no clue.


A : Your problem might be one which already have been solved on the DJGPP Newsgroup. DJ Delorie has set up a searchable Newsgroup archive on his Web server. You can search the entire mailing list archives in just a few seconds. DJ's archives are always up to date, as they receive and store all posted messages automatically, but the index is updated every 24 hours, so the last day might not be searchable yet. To search the DJGPP archives at DJ's, point your Web browser to the above URL and specify a list of keywords pertinent to your problem. You will get a list of messages which include those keywords; clicking on any of the messages will get the full text of that message. Stephen Turnbull has set up another search engine which you can use to search the entire Newsgroup archive for an arbitrary regular expression. Point your Web browser to that URL and do whatever the instructions you get tell you. You will receive a list of lines in the archive which contain your regexp, with a two-line surrounding context. You can use this to decide which parts of the archive you need to download and read.

Steve's archives can also be fast-searched. using any Web browser supporting ISINDEX capabilities. This is faster, but supports only simple keyword searches, not regular expressions. You can also download gzip'ed copies of DJGPP correspondence split up by months (the most recent month might not be up-to-date) from the anonymous ftp server set up by Stephen Turnbull. They are available at turnbull.sk.tsukuba.ac.jp. If you look for the traffic from a specific time period, you should look for files named djgpp.YYMM.gz (they are around 250K bytes each), where YY is the year and MM is the month number. E.g., for February 1996 traffic get the file djgpp.9602.gz. Alternatively, look for the file which holds list traffic for the year and the month you need with your Web browser. Once you have the Newsgroup archives, or a relevant portion(s) thereof, search for your problem by using some keywords specific to your problem, like "crash", "violation", etc. The archive is just a text file, so any text file viewer/editor with search capability can do it.

| Previous | Up | Top |

6.11 How to ask DJGPP gurus for help

Q: I've searched the Newsgroup archives, but didn't find anything helpful. I am totally lost. Help!!!

Q: I don't have time to download all these huge files, not to mention looking through them. Can't you DJGPP gurus help me? Please??


A : To get fast and effective solution to your problem, you will have to supply the relevant info about your system, and exactly in what way does it go wrong. To gather this info, do the following: Be warned that you might get several dozens of messages in reply to your request; this is not meant to overflow your mailbox or sabotage your relationship with your system manager, it's just the usual friendly response of fellow DJGPP'ers to your lonely cry for help. Some of the replies might suggest what you already checked and reported in your original message, or even miss the point altogether. Be ready for this and don't flame us for trying to help you as much as we can.

| Previous | Next | Up |

7. Compiler Performance

Q: Why GCC is compiling sooo slooowww?


A : That depends on what you mean by "slow". The following table gives "normal" gcc compilation speed, in source lines per second, on a 486DX2-66:

                 |  Without optimization  |  With -O2
      -----------+------------------------+------------
      C++ source |        200             |   100
      -----------+------------------------+------------
      C   source |        430             |   250

(Btw, these numbers are about 20% faster than you will get on a 40MHz Sparc2 box.) On machines faster or slower than 486DX2-66, scale these numbers appropriately. When comparing to this table, don't forget to count header files your program #include 's in the total line count. And don't check compilation speed on very short programs (like the classic "Hello, world!"), because the overhead of loading the multiple passes of the compiler will completely hide the compiler performance.

If your results are close to these (deviations of a few percents are considered "close" here), then that's as fast as you can get with GCC. If they are significantly lower, you may indeed have a problem; read on.

First, check to see if GCC pages to disk when it compiles. This is manifested by a heavy disk traffic which won't go away even if you have a large write-back disk cache installed. To be sure, disable the virtual memory services for your DPMI host (for CWSDPMI, use the SWSDPR0 as your DPMI host, or get the CWSPARAM program and change the swap filename to point to a non-existent drive), then run the compilation again: if the compiler aborts with an error message saying there isn't enough memory, then it is paging.

If paging does happen, you need to free more extended memory. If you have a RAM disk, make it smaller, or don't use it at all (it only makes compiles to run about 10% faster), or make your disk cache smaller (but don't discard the disk cache altogether); if you have other programs which use extended RAM, make them use less of it. Failing all of the above, buy more RAM (see the description of reasonable configuration). Also see recommendations for optimal software configuration.

If GCC doesn't page, check settings of your disk cache. If you don't use a cache, install one--this can slash your compilation times by as much as 30%, more so when compiling a large number of small files. If you already have a cache, enable its delayed-write (aka write-back, aka staggered-write) operation.

If you had some of the beta releases of v2.0 installed during the beta-testing period, be sure to upgrade your CWSDPMI to the latest version. The memory allocation scheme has been changed halfway through the beta-testing, which made old versions of CWSDPMI awfully slow when used with programs linked against the new library versions.

It is also worthwhile to check the settings of your system BIOS. In particular, the following items should be checked against your motherboard vendor recommendations:


     Internal and external CPU cache....set to Enable
     CPU cache scheme...................set to Write-back, if possible
     DRAM and SRAM wait states..........vendor-recommended optimal values

Incorrect or suboptimal settings of the above items can explain as much as 30% performance degradation on 486 machines, and as much as 500% (!) if you have a Pentium CPU.

DJ Delorie reports that his well-tuned 90 MHz Pentium system with 32 MBytes of RAM and 4 MBytes of RAM disk compiles the entire GCC source in about 20 minutes (this takes about 45 minutes on a 40MHz Sparc2).

For very large (several MBytes) executables which are built from a large number of small source files, the link stage might be the one which needs more RAM than you have free, and thus be the bottleneck of the time it takes to build your program. Check that the size of the executable isn't larger than the amount of your free RAM. If it is, then it might make sense to use a smaller (or even no) disk cache, and allow the linker as much physical RAM as it needs. Be sure that the linker wasn't stub-edited to make its transfer buffer too small (the default 16KB should be more than enough).

| Previous | Next | Up |

8. Compile-time and Link-time Problems

Being of a Unix origin, GCC has a somewhat different flavor of command-line syntax and its peculiar compilation and link algorithms. It also has a plethora of optional switches, some of them obscure or semi-documented. These are known to confuse users, especially those who had previous experience with DOS-based C compilers.

This chapter explains how to solve some of those problems which tend to appear when compiling and linking your programs.

| Previous | Next | Up | Top |

8.1 GCC can't find headers or libraries

Q: When I run the compiler it says it couldn't find header files and/or libraries. But the headers and libraries are all there, so why won't it find them?


A : In order for the compiler to find its include files, libraries and other stuff it can't do without, you should have the following variable set in your environment:

      DJGPP=c:/djgpp/djgpp.env

and it should point to the correct path of the file DJGPP.ENV on your system (the file itself comes with the file djdev200.zip in the DJGPP distribution). In the above example it is assumed to be in the C:/DJGPP directory, but you should set it as appropriate for your installation.

If the DJGPP variable is set correctly, then check the following possible causes of this misbehavior:

| Previous | Next | Up | Top |

8.2 GCC can't find C++ headers

Q: I installed all the packages, but GCC complains it can't find iostream.h, _string.h and other C++ headers. Where can I find those header files?

Q: GCC complains about it being unable to find Complex.h, Regex.h and other header files which start with a capital letter, and I indeed don't see them in my lang/cxx/ directory. Where are they?

Q: My C++ program needs header files whose filenames exceed the 8+3 DOS filename restrictions, like stdiostream.h and streambuf.h, and GCC cannot find those files. How in the world can I write portable C++ programs??


A : C++ include files are in the file lgp271b.zip. Files whose names usually start with a capital letter, on MS-DOS have an underscore `_' prepended so they could be distinguished from complex.h, regex.h and the like under case-insensitive DOS. Change Complex.h to _complex.h in your source, and GCC will find them.

If you have problems with header files with long filenames, and you run under Win95 or some other environment which allows for long filenames, try disabling the Long File Names (LFN) support in DJGPP, by setting the LFN environment variable to No, like this:


       set LFN=n

(DJGPP comes with LFN disabled by default on the DJGPP.ENV file, but you might have enabled it.) If this makes the problems to go away, then you have some conflict between the way LFN is supported by DJGPP and your environment. Under Win95, you must rename the files which should have long filenames to those long names (as opposed to the truncated names you find in the DJGPP archives). You must also set the option in the Win95 registry which disables name-munging of the files which have exactly 8 characters in their name part. This is how:

| Previous | Next | Up | Top |

8.3 GCC barfs on C++-style comments in C programs

Q: My C program compiles OK with Borland's C, but GCC complains about "parse error before `/' " at a line where I have a "//"-style comment.


A : That's because // isn't a comment neither in ANSI C nor in K&R C. Borland and Microsoft C compilers support it as an extension. GCC also supports this extension (beginning with version 2.7.0), but using the -ansi or -traditional switches to GCC disables this extension. In general, it's a bad practice to use this extension in a portable program until such time as the ANSI C standard includes it. If it's a C++ program, then rename it to have a suffix which will cause gcc to compile it as such (see list of language-specific suffixes), or use -x c++ switch. If it's a C program, but you want to compile it as C++ anyway, try -x c++; it can help, but can also get you in more trouble, because C++ has its own rules. For example, the following program will print 10 if compiled as a C program, but 5 if compiled as C++:

         #include <stdio.h>
     
         int
         main ()
         {
           printf ("%d \n" 10    //*
     		     / 2    //*/
     		       1
     		       );
           return 0;
         }

(While admittedly perverse, this little monstrosity was written with a the sole purpose to demonstrate that C and C++ have quite different semantics under certain circumstances.)

If you must have both -ansi and C++-style comments, you can use the -lang-c-c++-comments preprocessor switch. Gcc doesn't accept the -lang-XXX switches on its command line, so you will have to use the -Wp option, like this:


      gcc -c -Wp,-lang-c-c++-comments myprog.c

Alternatively, you can add -lang-c-c++-comments to the *cpp: section of your lib/specs file (but that will make it permanent).

Bottom line: until the future ANSI/ISO C standard includes this as part of the C language, it's best to change those comments to C-style ones, if you really mean to write a C program. The following Sed command will convert a C program with C++-style comments into a valid C source, provided you don't have the string "//" in a character string:


      sed "s?//\(.*\)?/*\1 */?" file.c > newfile.c

Sed can be found in the DJGPP distribution.

| Previous | Next | Up | Top |

8.4 How does GCC recognize the source language?

Q: I type GCC PROG.CC and GCC complains that it can't recognize PROG.CC's file format. How come a C++ compiler doesn't recognize a C++ source??

Q: I type GCC PROG.C to compile a C program which I already remember to pass compilation without a single warning, and suddenly it gives all kinds of strange error messages and unresolved externals.


A : That's because you typed your source file extension in upper case. GCC is not case-insensitive about filenames like DOS is, and it uses the file's extension to determine how to compile a file. Valid extensions are:
.cc
.C
.cxx
.cpp
C++ source (passed through cpp).
.c
C source that must be passed through cpp first.
.i
Raw C source (no cpp pass).
.ii
Raw C++ source (not to be preprocessed).
.m
Objective-C source.
.S
Assembler that must be passed through cpp first.
.s
Raw assembler source (no cpp pass).
Any other file is passed to the linker, under the assumption that it's an object file. In the examples above, PROG.C is taken as C++ program, not a C one, and PROG.CC is passed to the linker as if it were an object file. You can see what GCC does by adding -v switch to the GCC command line; if you see it's invoking cc1plus.exe (the C++ compiler) instead of cc1.exe (the C compiler), or calling ld.exe (the linker) on a source file, then you'd know this is your problem. If you have problems keeping up with the verbose GCC output caused by -v, see how to capture GCC output, in this FAQ.

You can override the default rules gcc uses to decide how each input file should be treated, with the help of -x LANGUAGE switch. For instance, the command


      gcc -x c++ prog.c

compiles prog.c as a C++ source. See the "Overall Options" section of the "The GNU C Compiler Manual", for more info on -x options.

| Previous | Next | Up | Top |

8.5 Problems with Objective C

Q: How do I tell gcc my .cc file is to be compiled as Objective-C source?

Q: I compile an Objective-C program, but get unresolved symbols.

Q: I can't compile the Objective-C test program which came with DJGPP.


A : Give your sources the .m extension, or use -x objective-c switch to GCC, so it will know you mean to compile with Objective C.

Objective-C was broken in GCC 2.6.0. The problem manifests itself by unresolved modules. If you use that version, you'll have to upgrade to version 2.6.3 or higher.

| Previous | Next | Up | Top |

8.6 Writing codes fragments which are specific to DJGPP

Q: I must put a DJGPP-specific code fragment into my program. What symbol should I use in the #ifdef directive to make it only visible under DJGPP?


A : Use __DJGPP__, like this:

         #ifdef __DJGPP__
         ... DJGPP-specific code ...
         #else
         ... not seen under DJGPP ...
         #endif

__DJGPP__ has a value of the DJGPP major revision number, so you can write code fragments which have different behavior under different versions of DJGPP:

         #ifdef __DJGPP__
         #if __DJGPP__ > 2
         .... will work only in DJGPP v3.x and later ...
         #else
         .... get here for DJGPP v2.x ...
         #else
         .... get here in DJGPP v1.x or non-DJGPP environment
         #endif

Another DJGPP-specific pre-processor symbol which DJGPP defines is __GO32__ ; but it is only provided for compatibility with previous versions of DJGPP (v1.x) and its use should be discouraged.

| Previous | Next | Up | Top |

8.7 Unresolved externals when linking programs

Q: Why do I get so many unresolved symbols when linking my programs?


A : By default, GCC instructs the linker to only look in two libraries: libgcc.a and libc.a. Some functions aren't included there, so the linker can't find them. GPL library routines, like obstack and regex packages are in libgpl.a library; append -lgpl to the link command line to use them. To use C++ classes in the libgpp.a (it's called libg++.a on Unix systems), append -lgpp. If you only use the iostream classes and don't want your program to be affected by the GNU Copyleft, use the libiostream.a library by appending -liostream (these are also included in the libgpp.a library).

When linking C++ programs, you can use the gxx instead of gcc command; it will then instruct the linker to also scan the C++ libraries.

If your program uses a lot of floating-point math, or needs math functions beyond those specified in the ANSI/ISO standard, consider appending -lm to your link command line. The basic math functions required by ANSI/ISO standard are included in the libc.a library, but libm.a includes higher quality versions of these functions, and also some functions not included in the default library, like Gamma function and Bessel functions.

| Previous | Next | Up | Top |

8.8 How not to lose your head with all these libraries

Q: I'm lost with all those different libraries. How in the world can I find out which functions are included in which library?


A : You can use the nm program to check what functions are included in a library. Run it with -C option and with the library as its argument and look in the output for the name of your function (the -C, or -demangle option makes the function names to look closer to what they are called in the source file). Functions which have their code included in the library have a capital T before their name. For example, the following is a fragment from the listing produced by nm:

         c:\djgpp\lib> nm --demangle libc.a
         .
         .
         .
         stdio.o:
         000000e4 b .bss
         000000e4 d .data
         00000000 t .text
         00000098 t L12
         0000001e t L3
         00000042 t L6
         0000004d t L7
         0000006a t L9
         00000000 t __gnu_compiled_c
     	     U _filbuf
     	     U _flsbuf
         00000000 T clearerr
         000000ac T feof
         000000c2 T ferror
         000000d8 T fileno
         0000000c T getc
         00000052 T getchar
         0000002a T putc
         0000007c T putchar
         00000000 t gcc2_compiled.
         .
         .
         .

Here we see that the module stdio.o defines the functions clearerr, feof, ferror, fileno, getc, getchar, putc and putchar, and calls functions _filbuf and _flsbuf which aren't defined on this module.

Alternatively, you can call nm with the -s or -print-armap, which will print an index of what symbols are included in what modules. For instance, for libc.a, we will see:


         c:\djgpp\lib> nm --print-armap libc.a
         .
         .
         .
         _feof in stdio.o
         _ferror in stdio.o
         _fileno in stdio.o
         .
         .
         .

which tells us that the functions feof, ferror and fileno are defined in the module stdio.o.

nm is fully described in the GNU docs. See the "nm" section of the "GNU Binutils Manual".

| Previous | Next | Up | Top |

8.9 DJGPP uses a one-pass linker

Q: I give all the libraries to gcc, but I still get unresolved externals when I link. What gives?


A : Ld is a one-pass linker, it only scans each library once looking for unresolved externals it saw until that point . This means the relative position of object files and libraries' names on the command line is significant. You should put all the libraries after all the object files, and in this order:

      -lgpp -lgpl -lm

E.g., to link files main.o and sub.o into a C++ library, use the following command line:

      gcc -o main.exe main.o sub.o -lgpp -lgpl

or, if you compile and link in one command:

      gcc -o main.exe main.cc sub.cc -lgpp -lgpl -lm

If you have any libraries of your own, put them before the above system libraries, like this:

      gcc -o main.exe main.cc sub.cc -lmylib -lgpp -lgpl -lm

When you use the gxx compilation driver to compile a C++ program, it names the C++ libraries in the correct order.

If your installation tree is different from the default, i.e., if you keep the libraries not in the default lib/ subdirectory, then you should add that directory to the line in the [gcc] section of your DJGPP.ENV file which starts with LIBRARY_PATH, or put into your environment a variable called LIBRARY_PATH and point it to the directory where you keep the libraries. Note that if you invoke the linker by itself (not through the gcc driver), then LIBRARY_PATH will have no effect, because this variable is only known to the gcc driver. So if you must call ld from the command line, use the -L option to tell it where to look for the libraries.

| Previous | Next | Up | Top |

8.10 C++ functions still not found

Q: I put all the libraries in the above order, but the linker still can't find some C++ functions from complex.h and iostream.h.


A : These functions are declared inline and defined on these header files. However, GCC won't inline them unless you compile with optimizations enabled, so it tries to find the compiled version of the functions in the library. Workaround: compile with -O.

| Previous | Next | Up | Top |

8.11 The linker complains about __pure_virtual function.

Q: When I link a C++ program, the linker complains about "__pure_virtual" being an unresolved symbol. What should I do?


A : This problem is caused by a libgcc.a library which lacks a module called ___pure_virtual (yes, with three leading underscores!). You should get an updated version of that library which includes such a module. libgcc.a comes with the Gcc distribution, so look in the latest gccNNNb.zip file.

If, for some reason, you cannot find libgcc.a with that module, you can add it yourself. To this end, create a file called pure.c with this content:


     #define MESSAGE "pure virtual method called\n"
     
     void __pure_virtual()
     {
         write(2, MESSAGE, sizeof(MESSAGE) - 1);
         _exit(-1);
     }

Compile this file and put the object file into libgcc.a, like this:

             gcc -c pure.c
             ar rvs libgcc.a pure.o

That's all!

| Previous | Up | Top |

8.12 C++ programs yield large .exe file

Q: It seems that declaring a large static array has an effect of bloating the program image on disk by that many bytes. Surely there is a more compact way of telling the loader to set the next N bytes of RAM to zero?


A : This only happens in C++ programs and is a (mis-)feature of GCC. You can use the -fconserve-space switch to GCC to prevent this from happening, but it also turns off the diagnostics of duplicate definitions, which, if uncaught, might cause your program to crash. Thus, this switch isn't recommended for programs which haven't been completely debugged (if there is such a creature). The -fconserve-space switch is described in the GCC docs, See the "C++ Dialect Options" section of the "GNU C Compiler Manual".

If the downside of using this switch doesn't deter you, you can even add this switch to your lib/specs file to make it permanent.

| Previous | Next | Up |

9. Running Compiled Programs

This chapter discusses various problems which may happen when running DJGPP programs under different environments, and gives solutions to them.

| Previous | Next | Up | Top |

9.1 My program crashes only in v2.0!

Q: I have this program which runs fine when compiled with DJGPP v1.12, but crashes and burns in v2.0. Isn't it obvious that you guys blew it with v2.0?

Q: My v2.0 program crashes, but only under CWSDPMI; it runs OK under other DPMI hosts like Windows, OS/2 or QDPMI. Is this a bug in CWSDPMI?


A : Not necessarily so, it could still be a bug in your program which just went unnoticed in v1.12. One area where such things can happen is use of uninitialized memory. In v1.x, memory first allocated to the stack or by a call to malloc is always zeroed, but v2.0 doesn't behave this way, so your program might exhibit erratic behavior or crash with SIGSEGV because of such bugs. In particular, if the program behaves differently depending on which program was run before it, you might suspect bugs of this kind.

To check whether this is the source of your grief, include the header crt0.h in your main and set _crt0_startup_flags to _CRT0_FLAG_FILL_SBRK_MEMORY ; this will fill the memory with zeroes when it is first allocated. If the program will run OK after recompilation, then this is probably the cause of your problem. To make spotting uninitialized memory simpler, you can set _crt0_startup_flags to _CRT0_FLAG_FILL_DEADBEAF (don't laugh!) ; this will cause the sbrk()'ed memory to be filled with the value 0xdeadbeaf which is easy to spot with a debugger. Any variable which has this value, was used without initializing it first.

Another possible cause of problems will most probably be seen under CWSDPMI. Unlike other DPMI hosts, CWSDPMI supports some DPMI 1.0 extensions which allow DJGPP to capture and disallow illegal dereference of pointers which point to addresses less than 1000h (aka NULL pointer protection). This feature may be disabled by setting the _CRT0_FLAG_NULLOK bit in _crt0_startup_flags ; if this makes SIGSEGV crashes to go away, your program is using such illegal pointers.

| Previous | Next | Up | Top |

9.2 What is that gibberish printed when my program crashes?

Q: My program dies with a cryptic message like "Segmentation violation" or "Unsupported DOS request" or "General Protection Fault" and prints some funny-looking numbers. Can't I get some decent human-readable traceback information, so I could pinpoint where in the program did the problem happen?


A : Those "funny-looking numbers" are the traceback. They describe the sequence of function calls which led to the fatal error by giving you the addresses where each function was called. You can have these addresses translated to source line numbers by using the SYMIFY program (it is included in the djdev200.zip, and should be in your bin/ subdirectory). To this end, make sure that your program was compiled with -g switch, linked without -s switch and not stripped, and that you have the source files available in your current directory. Now invoke your program and do whatever it takes to make it crash. Then, with the traceback still on the screen, type this from the DOS command line:

      symify your-program-name

You will see the list of source files and line numbers right next to their hex addresses. Now you can start debugging.

You can ask SYMIFY to put the stack trace into a file (so you can consult it later, e.g., from your editor while fixing the bug), by giving it an output file, like this:


      symify -o problem.dmp yourprog

You can also save the raw stack trace (without source info) to a disk file and submit it to SYMIFY later, like this:

      symify -i core.dmp yourprog

This comes in handy when your program grabs the screen (e.g., for some graphics) and the stack trace can't be seen. You can then redirect the stack trace to a file, e.g., with theREDIR program which comes with DJGPP.

But what if you didn't compile your program with -g, and you aren't sure how to recreate the problem which crashed it, after you recompile? Well, you can submit the stack dump after you recompile your program. Just press that PrintScreen key or otherwise save the stack trace, then submit it to SYMIFY from a file as described above, after you've recompiled the program. Be sure to give gcc all the compilation switches (sans -s) that you gave it when you originally compiled your program (in addition to -g), including the optimization switches, or else the addresses shown in the stack trace might be invalid.

| Previous | Next | Up | Top |

9.3 Reading and writing binary files

Q: I'm reading/writing data files, but the data gets corrupted.

Q: When I read a file I get only a small portion of it.


A : Are your data files binary? The default file type in DOS is "text", even when you use read and write library functions. Text files get their Newlines converted to CR-LF pairs on write and vice versa on read; reading in "text" mode stops at the first ^Z character. You must tell the system that a file is binary through the b flag in fopen, or O_BINARY in open, or use the setmode library function. You can also use the low-level _read and _write library functions which give you the direct interface to the DOS file I/O.

| Previous | Next | Up | Top |

9.4 Buffered screen I/O surprises

Q: My program prompts the user to enter data from the keyboard, then reads its response. When compiled with a 16-bit compiler like BCC or MSC it works as expected, but with gcc the prompt doesn't show, or is printed much later in the program.


A : Do you write to screen using buffered I/O ( fprintf, fputs and the like) functions? Then maybe your program defined a large buffer for standard output streams. If so, the buffer is not written to screen until it's full, which might produce very unpleasant and unexpected behavior when used in interactive programs.

It is usually bad idea to use buffered I/O in interactive programs; you should instead use screen-oriented functions like cprintf and cputs . If you must use buffered I/O, you should be sure that both stdout and stderr are line-buffered or unbuffered (you can change the buffering by calling the setvbuf library function); another solution would be to fflush the output stream before calling any input function, which will ensure all pending output is written to the operating system. While this will work under DOS and DJGPP, note that some operating systems (including some DOS extenders) might further buffer your output, so sometimes a call like sync would be needed to actually cause the output be delivered to the screen.

| Previous | Up | Top |

9.5 What do DJGPP programs need to run?

Q: When I copy my DJGPP application program to another PC where no DJGPP is installed, I can't run it. It complains that it cannot find DPMI (??). Do I really need all of your multi-megabyte installation to run compiled programs?


A : No, you don't. You can either (1) bring the CWSDPMI.EXE free DPMI host to the target machine and put it in the same directory as your compiled program or somewhere along the PATH, or (2) install another DPMI host (such as QDPMI, 386Max, Windows, etc.) on the target machine. Note that the author of CWSDPMI, Charles W Sandmann, requests a notification by mail or acknowledged e-mail in case you distribute CWSDPMI with a commercial or shareware products.

If your program could be run on a machine which lacks floating-point processor, you should also distribute an emulator, or link your program with an emulator library. See floating-point emulation issues.

Future DJGPP releases might have a way to bind your executable with CWSDPMI to produce a stand-alone program. If you need such a feature now and if you need it badly, ask Charles W Sandmann to make this happen as soon as he can.

| Previous | Next | Up |

10. Writing and Running Graphics Programs

This chapter discusses some problems and explains some subtle points related to graphics programming under DJGPP.

| Previous | Up | Top |

10.1 Accessing the video memory

Q: I try to access the video memory at 0xa0000, but get "Segmentation violation" ...

Q: How can I access the text-mode video memory of my VGA?


A : Absolute addresses of memory-mapped devices are mapped differently under DJGPP, than what you might be used to under other DOS development environments. That's because DJGPP is protected-mode environment, where you can't just poke any address: that's what protected mode is all about! To access such absolute addresses, use the so-called "farptr" functions like _farpeekb and _farpokew ; they are described in the C Library reference. See more details on using "farptr" functions to access absolute addresses in low memory, below.

For text-mode screen updates, you can also use the ScreenUpdate and ScreenUpdateLine library functions to quickly update the screen from a text buffer.

Using _farpeekX / _farpokeX paradigm to access memory isn't much slower than direct access (they compile into 2 machine instructions when optimizations are enabled). But if you need even more fast access (and don't want to write it in assembly), See using the "nearptr" access facilities, as described below.

| Previous | Next | Up |

11. Floating Point Issues and FP Emulation

This chapter deals with issues pertaining to floating-point code and floating-point emulation under DJGPP.

| Previous | Next | Up | Top |

11.1 Floating code without 80387

Q: I don't have an 80387. How do I compile and run floating point programs?

Q: What shall I install on a target machine which lacks hardware floating-point support?


A : Programs which use floating point computations and could be run on machines without 80387, should either be linked with libemu.a emulation library (add -lemu to your link command line) or be allowed to dynamically load the emu387.dxe file at run-time if needed. Linking with libemu makes distribution simpler at a price of adding about 20KB to the size of the program .exe file (the emulator functions will be used only if no hardware floating point support is detected at runtime). You should always do one of the above when you distribute floating-point programs.

A few users reported that the emulation won't work for them unless they explicitly tell DJGPP there is no x87 hardware, like this:


       set 387=N
       set emu387=c:/djgpp/bin/emu387.dxe

There is an alternative FP emulator called WMEMU (get the file v2misc/wmemu2b.zip). It mimics a real coprocessor more closely, but is larger in size and is distributed under the GNU General Public License (which generally means you need to distribute its source if you distribute wmemu387.dxe, or distribute the source or objects to your entire program, if you link it with libwmemu.a). Its advantage is that with WMEMU, you can debug FP apps on a non-FPU machine.

| Previous | Next | Up | Top |

11.2 Other FP emulators cannot be used with DJGPP

Q: I have an 80387 emulator installed in my AUTOEXEC.BAT, but DJGPP-compiled floating point programs still doesn't work. Why?


A : DJGPP switches the CPU to protected mode, and the information needed to emulate the 80387 is different. Not to mention that the exceptions never get to the real-mode handler. You must use emulators which are designed for DJGPP.

| Previous | Next | Up | Top |

11.3 Floating-point emulation under OS/2

Q: I run DJGPP in OS/2 DOS box, and I'm told that OS/2 will install its own emulator library if the CPU has no FPU, and will transparently execute FPU instructions. So why won't DJGPP run floating-point code under OS/2 on my machine?


A : OS/2 installs an emulator for native OS/2 images, but does not provide FPU emulation for DOS sessions.

| Previous | Next | Up | Top |

11.4 DJGPP doesn't support -msoft-float

Q: I've read in the GCC Info file that gcc has a -msoft-float option which is said to generate library calls for floating point support. Can this facility be used for FP emulation on a machine without x87?


A : Gcc Info file also says that the library required by -msoft-float is not part of GNU C compiler. As nobody wrote such a library for DJGPP (yet), this option currently isn't supported.

| Previous | Next | Up | Top |

11.5 Numeric exceptions--sometimes

Q: I have a program which works with FP emulation, but dies with "Numeric Exception" when run on a machine with a co-processor. It also runs OK when compiled with Microsoft C. Can't you people make your floating-point code right?


A : This might be still a problem with your program. Under DJGPP, the 80x87 control word is set up so that it generates an exception when your program feeds it with a NaN ("Not a Number"), while the emulator doesn't have this behavior. You should check that your program doesn't generate NaNs, or set 80x87 control word to a different value. There is a program called ctrl87.c, which enables this kind of diddling the 80x87 control word; check it out. There is also a library function called _control87 which can be used from within a program to set the coprocessor to a non-default state.

| Previous | Up | Top |

11.6 Floating point inaccuracies when using emulator

Q: I am experiencing inaccurate results in some floating point calculations, sometimes in the 2nd or 3rd significant digit (like getting 118.401 instead of 120.0). This is really unacceptable! (And no, I'm not using a buggy Pentium CPU.)


A : Are you using the emulator? If so, it might be that the emulator isn't as accurate as you expect. One particular known problem is that it does a bad job when computing atan function. So if you use atan(1.) to get the value of Pi, that might be your problem. Solution: make Pi a constant, as God intended. The header file includes the constant M_PI which you can use; or get the value of Pi from the net.

| Previous | Next | Up |

12. Debugging DJGPP Programs

This chapter discusses the debuggers you can use with DJGPP and answers some of the questions you might have when debugging DJGPP programs.

| Previous | Next | Up | Top |

12.1 How to run a DJGPP program under debugger

Q: How do I debug my programs?


A : First, remember to use the -g switch when you compile and link. This puts debugging information into your executable. When linking, don't use the -s switch, and give the name of the output file without the .exe extension , so that gcc would leave both the COFF output and the DOS executable after the link stage. Here are a few examples of compilation and link command lines when you intend to debug a program:

      gcc -Wall -c -g -O myfile.c
     
      gcc -Wall -O2 -g -o myprog mymain.c mysub1.c mysub2.c -lm
     
      gcc -g -o myprog myprog.o mysub.o

(Note that with gcc, you can use optimization switches when compiling with -g.) Then, to debug the program, use a command line like this (here for gdb):

      gdb myprog

You can use on of several available debuggers with DJGPP:
  1. FSDB, the full-screen debugger, from the djdev distribution. This presents a user interface like that of Borland's Turbo Debugger, but unlike TD, it isn't a source-level debugger (although it will show the source code together with the machine instructions). It also supports data-write breakpoints: a powerful feature for hunting down code which overwrites data it shouldn't touch.
  2. The GNU Debugger, GDB (get the file gdb412b.zip. This is a powerful source-level debugger, but it uses a line-oriented user interface. Note that the initial commands are read from a file named gdb.ini instead of .gdbinit which is illegal filename under MS-DOS.
You invoke any debugger like this:

      <debugger-name> <program> <args...>

| Previous | Next | Up | Top |

12.2 You need QEMM 7.53 or later

Q: Whenever I call any DJGPP debugger to debug my program, it crashes immediately.


A : Are you running under Quarterdeck's QDPMI? Then you should upgrade to QEMM 7.5 patch-level #3 or later. That patch corrects a subtle problem in QDPMI which was triggered by the debugger. If you cannot or wouldn't upgrade, for money or love, turn OFF the DPMI services of QDPMI and use CWSDPMI as your DPMI host. To disable QEMM DPMI services either uninstall QDPMI, or go to the QEMM directory and issue the following command:

      qdpmi off

| Previous | Next | Up | Top |

12.3 GDB won't debug unless it sees COFF output

Q: I try invoking GDB on my program, but it says: "not in executable format: File format not recognized." Huh?


A : Most probably, you've invoked GDB on a .exe program. GDB needs to be called with the name of un-stubbed COFF executable as its argument. To get both a .exe and a COFF file, you should make your link command line to look this way:

      gcc -o foo foo.o

instead of

      gcc -o foo.exe foo.o

(the latter will only produce foo.exe, while the former produces both foo, the COFF executable which gdb needs, and foo.exe). To produce a COFF file from a .exe program, use the EXE2COFF program which comes with DJGPP, like this:

      exe2coff foo.exe

| Previous | Next | Up | Top |

12.4 Debuggers use the transfer buffer.

Q: My program corrupts files and screen writes, and otherwise behaves strangely when run under a debugger.


A : Do you use the transfer buffer to move data between your program and conventional (under 1 MByte) memory? Then it might be that the debugger corrupts your I/O. The debugger itself uses the transfer buffer for disk read requests and screen writes. If you single step through any of your app routines which use the transfer buffer, the debugger might overwrite its contents, which may alter the correct behavior.

To work around this, don't step with the debugger through your functions which use the transfer buffer.

If all of the above doesn't make sense for you, don't worry: if you don't know what the transfer buffer is, and you only trace into your own functions, then you won't hit this problem.

| Previous | Next | Up | Top |

12.5 How to debug a graphics program

Q: How can I debug a graphics program? The debugger runs my program fine, but when a breakpoint is hit with the screen in a graphics mode I can't read the text printed by the debugger.


A : Redirect the debugger output to your printer, like this:

      gdb myprog > prn

This will only work if the program itself doesn't write to stdout (this is usually the case with graphics programs); otherwise the debugger output will get mixed up with your program's output.

The FSDB debugger can switch between the application screen and the debugger screen, so you might use it, at a price of working with low-level debugger. Press Alt-F5 to switch between the two screens.

As yet another possibility, consider using the MSHELL program which will redirect I/O from any program to the monochrome, monitor at the BIOS level, so you can use it even with GDB. MSHELL was written by DJ Delorie and is available as mshell10.zip.

| Previous | Next | Up | Top |

12.6 GDB finds only .cc source

Q: When I try to debug my C++ programs, the debugger claims it can't find the source file:


      file.cc: No such file or directory.

The source file is there, but it's called file.cpp, not file.cc. Why does this happen?
A : It's a bug in GCC. It erroneously assumes that a C++ source always has a .cc extension. Until this bug is corrected in some future version of GCC, you're better off calling your C++ files *.cc. If this is unacceptable, then you can work around this bug by invoking cc1plus and the assembler pass manually. The bug in GCC manifests itself in that cc1plus is called with the option -dumpbase file.cc. If you replace this with -dumpbase file.cpp (or whatever your extension is), the debugger will happily find your sources.

| Previous | Up | Top |

12.7 Debuggers choke on some programs ...

Q: I cannot debug Emacs (or any program that requests raw keyboard input): when I press Ctrl-C, any debugger I tried reported SIGINT. But I cannot operate the debugged program without Ctrl-C (in Emacs, it's necessary to exit the editor)!

Q: I cannot debug any program which catches signals!!??

Q: I compiled my program with -pg switch, and now I cannot debug it...


A : There are currently a few limitations in debugging programs which use interrupts or exceptions. Programs compiled for profiling may crash with SIGSEGV or a GPF, with no addresses that symify can identify; programs using alarm or setitimer can't be debugged, either. You can't hook the keyboard interrupt in a debugged program, and you can't debug a program which uses floating point on a machine without an FP hardware (unless you use WMEMU as your emulator). If your program catches signals, the debugger will catch them instead and they won't get passed to the debuggee.

At least some of these limitations will be fixed in future versions of DJGPP. For now, the only work-around that's available is for the case that you need a Ctrl-C keypress to go to the debuggee instead of the debugger: use the Alt-Numeric-3 (that is, simultaneously press the Alt key and the 3 key on the numeric keypad, then release the Alt key).

| Previous | Next | Up |

13. Profiling DJGPP Programs

This chapter explains how to optimize your program for speed using the profiler, and discusses some problems you might have with it.

| Previous | Next | Up | Top |

13.1 How to profile a DJGPP program

Q: How can I profile my program to see where it spends most of its run time?


A : DJGPP includes a profiling facility. To use it, compile and link with -pg option, run your program as you usually would, then run a program called gprof:

      gprof myprog

(change myprog to whatever name your program is). This will print an execution profile.

Gprof is part of GNU Binutils distribution.

| Previous | Next | Up | Top |

13.2 Gprof won't work unless it can find COFF executable

Q: When I run Gprof, it complains that it cannot find my program. But I've just run it!!

Q: I run Gprof on my program, and it says: "bad format".


A : Gprof needs the original COFF file the linker produced. If you delete it, or feed Gprof with the .exe file instead, it will be most unhappy. The way to produce the COFF output is explained in the section dealing with GDB, above.

| Previous | Next | Up | Top |

13.3 Where is Gprof docs?

Q: What about all those Gprof options? Where can I find their docs?

Q: I can't figure out some of the info in Gprof report ...


A : Gprof is only documented on a man page, gprof.1. If you don't have one, you will have to look for it in the Binutils distribution.

| Previous | Up | Top |

13.4 Why is __dpmi_int so heavy used?

Q: I've profiled my program and found that the routine which takes 60% of the running time is some obscure library function called __dpmi_int . Can't you guys make your library right?


A : Does your program use I/O or other real-mode services (like BIOS) extensively? All those services are invoked through a DPMI service call which is issued by __dpmi_int . So what the profile really says is that the running time of your program is governed by time-consuming operations such as disk I/O.

| Previous | Next | Up |

14. Run-time Performance of DJGPP Programs

This chapter deals with issues pertinent to run-time performance of DJGPP programs.

| Previous | Next | Up | Top |

14.1 How efficient is DJGPP-generated code?

Q: How does DJGPP compare with other DOS-based C compilers in terms of efficiency of generated code?

Q: Won't my program run much slower when compiled by DJGPP, due to all those CPU cycles wasted in switches between protected and real mode?


A : The quality of code generated by GCC with optimization turned on (-O2 switch to the compiler) is generally at least as good as what you will get from top commercial products, like Borland, Microsoft and Watcom. Mode switches indeed have a certain performance hit, but in most programs it is negligibly small, because only DOS and BIOS services require such a switch, and most programs spend most of their time doing other things.

| Previous | Next | Up | Top |

14.2 My program's I/O is so slow!

Q: I measured time required to read a 2 MByte file in DJGPP and in Borland C. It took DJGPP program 2.5 seconds to do it, while Borland did it in just under 2. Isn't that horribly slow performance??

Q: I tried to improve DJGPP I/O throughput by defining a 64KB-large buffer for buffered I/O with a call to setvbuf, but that had no effect. Why is that?


A : Doing I/O from protected-mode programs requires that low-level library functions move the data between the extended memory and low memory under 1 MByte mark, where real-mode DOS can get at it. This area in the low memory is called the transfer buffer. This data shuffling means that some I/O speed degradation is inevitable in any protected-mode program which runs under DOS. By default, DJGPP moves data in chunks of 16 KB, so defining a buffer larger than that won't gain anything. The size of transfer buffer is customizable up to a maximum of 64 KB, so if your program really reads a lot of large files, you might be better off enlarging it (with the STUBEDIT program).

That said, I would like to point out that waiting another 0.5sec for reading a 2 MByte file isn't that bad: it is indeed about 25% longer than you can do under DOS, but it's only half a second... Besides, most programs read and write files which are only a few hundreds of kilobytes, and those will suffer only a negligible slow-down.

| Previous | Up | Top |

14.3 My ported program runs much slower!

Q: How come my program, which I ported from Borland C and which doesn't use much I/O, still runs much slower under DJGPP?


A : Explore the following possible causes for this:
  1. Your program extensively calls services other than I/O which require mode switch (like BIOS Int 10h, mouse services, etc.).

    You can tell how much your program switches to real mode by profiling your program. In the profile, look at the proportion of time your program spends in low-level library functions called __dpmi_int (which calls real-mode DOS/BIOS services) and __dj_movedata (which moves data between the transfer buffer and your program). If this proportion is large, try rewriting your program to minimize use of those functions which require a mode switch, even at a price of more computation (a mode switch usually eats up hundreds of CPU cycles).

  2. Your program uses library functions/classes which are implemented less efficiently by GCC. Or you might be a heavy user of functions which other compilers convert to inline code, while GCC doesn't inline most library functions. If this is the case, you will see those functions as "hot spots" on the program histogram produced by the Gprof profiler. If you find this to be the problem, write your own, optimized versions of those functions. It's best to write them as inline assembly functions, for maximum performance. If you find library functions which are inefficient, please inform the DJGPP newsgroup by posting to comp.os.msdos.djgpp, so this could be fixed by people who maintain the library.

  3. If your program spends most of its time in a certain innermost loop, you might try enabling the strength-reduction optimizations. This is disabled by default, because GCC has a known bug which sometimes causes it to generate incorrect code when this kind of optimization is enabled. If you decide to enable it, examine the behavior and the output of your program carefully, to be sure you didn't hit that bug.

| Previous | Next | Up |

15. Run-Time Memory Issues

This chapter answers questions which are related to DJGPP run-time memory allocation.

| Previous | Next | Up | Top |

15.1 How much virtual memory do you have?

Q: How much virtual memory can I use in DJGPP programs?


A : That depends on the DPMI host you are using. CWSDPMI (the free DPMI host which comes with DJGPP) will let you use all available conventional and extended memory (up to 128M) and up to 128M of disk space, for a grand total of 256M of virtual memory for your application. Try a malloc(50*1024*1024) some day.

With other DPMI hosts, your mileage may vary. Quarterdeck's QDPMI, for instance, has a bug in some of its versions which effectively disables virtual memory under DJGPP (described under QDPMI VM bug, below), so you only have whatever free physical RAM is left. Under Windows 3.x, the amount of virtual memory you get depends on various virtual memory settings in the Control Panel and on the .pif file settings for the program you run (see Windows allocation subtleties, below).

| Previous | Next | Up | Top |

15.2 It seems malloc / free don't affect virtual memory...

Q: I did malloc(50*1024*1024), but didn't see any paging happen, and I only have 8 MBytes of RAM on my machine. Is this virtual memory thing for real?

Q: I malloc 'ed a large chunk of memory, but when I check values returned by _go32_remaining_physical_memory or __dpmi_get_memory_information, I don't see any change...

Q: When I free allocated RAM, _go32_remaining_physical_memory reports there was no change in the available RAM.


A : CWSDPMI (and, possibly, other DPMI hosts) only pages in memory when it is actually accessed. If you only malloc it, but don't actually access it, it won't grab those pages. Try calloc and see the big difference.

When you call free, DJGPP library doesn't return memory to the system, it just adds it to its internal pool of free pages. So, from the system point of view, these pages are not "free".

| Previous | Next | Up | Top |

15.3 Failure to get more memory than is physically installed

Q: When I try to access more memory than the free physical RAM, malloc returns a NULL pointer, or I get some cryptic error message like this:


     DPMI: Not enough memory (0x00860000 bytes)

or like this:

     QDPMI: Memory Paging Violation: Illegal Page Reference [PTE=0000-0000h]
            [CR2=8006-3000h at 00E7h:0000-4936h]
     
     QDPMI: Unrecoverable Exception: 000Eh at 00E7h:0000-4936h.  Error Code = 0006h


A : This is typical of Quarterdeck's DPMI host called QDPMI which comes with QEMM386 version 7.53 and earlier. Some versions of QDPMI (those which come with QEMM v6.x) fail to resize memory block when the new size is more than available physical RAM, even though virtual memory services are enabled; other versions (those which come with QEMM v7.x) just don't let you allocate more memory than is physically available. If you must use more RAM than is physically available, disable or uninstall QDPMI, and use CWSDPMI instead.

This bug was corrected in QDPMI version 1.10 or later, distributed with QEMM beginning with version 8.0, so upgrading to the latest version of QEMM might also be a solution. With QEMM 6.x, make sure your programs don't override the default type of sbrk behavior by setting _crt0_startup_flags to _CRT0_FLAG_UNIX_SBRK (QEMM 8.0 and later can allocate virtual memory with both types of sbrk algorithm).

If you use another DPMI host, make sure that virtual memory is enabled. E.g., for 386Max, include the swapfile= parameter to establish a virtual memory swap file; you can make it permanent (this will speed up DJGPP start-up) with the /p option.

| Previous | Next | Up | Top |

15.4 Memory allocation fails under QDPMI

Q: OK, I've changed my program to never allocate more memory than is physically available, to work around that QDPMI VM bug, but my program still gets a NULL pointer from malloc / calloc !


A : Another peculiarity of QDPMI which came with QEMM before version 8.0: it will never let you allocate a chunk which is larger than half of what's available. Several people reported the same to be true under Windows 95.

With some DPMI providers, this behavior might be triggered by a small overhead of each malloc call: you might ask for half of available memory, but the DJGPP implementation of malloc adds the overhead and then rounds the amount of memory to the next power of 2 before calling sbrk ; thus malloc(8MB + 1) will actually request 16MBytes from the DPMI host. When in doubt, call sbrk directly, especially if you don't plan to free that memory during execution.

| Previous | Next | Up | Top |

15.5 Memory allocation fails under Windows

Q: I'm running under Windows 3.x DOS box, but DJGPP complains about there not being enough DPMI memory, although virtual memory is enabled.


A : You must make sure the size of your Windows swap file can be at least 2 times the largest virtual memory size you need. Check if you have enough free disk space; if you do, run a defragger (Windows needs the swap file to be contiguous). This size is normally limited by the the "virtual = 4 times free physical" rule, but you can change that by inserting the line

      PageOverCommit=n

in the [386Enh] section of your SYSTEM.INI file. The parameter n is 4 by default, but can be set to be as large as 20.

| Previous | Next | Up | Top |

15.6 Memory allocation fails under EMM386 or HIMEM

Q: My machine has 48 MBytes of RAM, but when I run DJGPP programs, they start paging after 32 MBytes has been used...

Q: I have 5 MBytes of free RAM on my machine, but DJGPP programs start paging after only 256KBytes of memory were used??


A : This might be caused by some old version of memory manager installed in your machine (like HIMEM or EMM386 from an old version of DOS), which were limited to 32 MBytes of expanded memory. Try running without them (CWSDPMI can use raw extended memory), or upgrade to a newer version of DOS.

If your programs start paging after only 256KBytes of memory were used, most probably you are using EMM386 and CWSDPMI, and your CONFIG.SYS specifies no amount of memory when it installs EMM386. EMM386 defaults to 256K in this case; you should tell EMM386 explicitly how much memory should it take over. You can use the go32-v2 program to see what amount of extended memory your DJGPP programs will get.

| Previous | Next | Up | Top |

15.7 How much memory do parent DJGPP programs leave for their child?

Q: How much memory is available when I use the system call?


A : In the conventional (below 640K mark) memory, you are left with everything which was free before your program started, except what the DPMI host uses. The amount of conventional memory required by the DPMI host depends heavily on the host you use. For the first DJGPP program, QDPMI uses about 97K, CWSDPMI uses about 70K, Windows 3.x only 18 KBytes. Each subsidiary call to system (like in recursive invocation of Make) eats up about 18K (16K for the transfer buffer and 2K for the PSP and environment) for most DPMI servers; a notable exception is QDPMI which needs 97K bytes of low memory for the subsequent calls too. If you change the size of the transfer buffer (with STUBEDIT ), the amount of free conventional RAM will change accordingly.

Extended memory management is left to the DPMI server; DJGPP does nothing special about XMS when system is called. This means that all the extended memory used by the parent program is not freed when the child program starts; if the child requests more memory than is physically free, the DPMI server is expected to page some of the parent out to honor the request. (This is unlike DJGPP v1.x, where the go32 extender would completely page out the parent before starting the child.) The advantage of this is that spawning a child or shelling out is much faster in v2.0 than it used to be with v1.x.

| Previous | Up | Top |

15.8 How much stack can I have in DJGPP programs?

Q: My program bombs when I use very large automatic arrays.

Q: How much stack space do I have in my program?

Q: My program crashes with SIGSEGV, but the traceback makes no sense: it points to something called ___djgpp_exception_table... When I try to debug this, the traceback mysteriously changes to some innocent library function, like getc(). The same program works flawlessly when compiled with DJGPP v1.x What's going on??


A : DJGPP v2.0 programs impose a limit on the maximum stack size; this is a bug/feature of the DPMI 0.9 specification. By default, you have a 256KB-long stack, but some programs which use large automatic arrays, or are deeply recursive, might need more. If the default stack size is not enough, you can change it with STUBEDIT program (change the parameter "Minimum amount of stack space"), or by setting the global variable _stklen in your program. Example:

      extern unsigned _stklen = 1048576;

Setting _stklen makes sure your program always works, but wastes memory, since the 256K stack originally allocated must be discarded. The best bet is to do both--setting _stklen in your program will ensure it works, but also using STUBEDIT to set a slightly (by a few KB) larger amount than the value of _stklen, will ensure the original stack won't have to be reallocated, and you will save the wasted memory.

Programs which needs an unusually large stack might crash with bogus stack trace, because parts of the heap get overwritten by the overflowing stack. To see if that is the cause of such crashes, run stubedit on your program and crank up the stack size to a large value (like 4MBytes). If that makes the problem go away, tune the stack limit to the minimum value your program can live with, then set _stklen to an appropriate value as explained above. (Some DPMI hosts will actually allocate the stack, even if not all of it is used, so leaving it at unnecessarily large value will hurt the program on low-memory machines.)

Some users have reported that they needed to enlarge the stack size of the C++ compiler, cc1plus.exe, to prevent it from crashing when compiling some exceedingly large and complex C++ programs. Another program that was reported to need a stack larger than the default is bccbgi.exe from the BCC2GRX package.

After you've used STUBEDIT to change the stack size, run it again to make sure it displays as default the value you thought you entered. This is because STUBEDIT will sometimes silently set the stack size to 0 (and then you will get the default 256K stack) if it doesn't like the value you type.

Under Windows, be sure you've allocated a sufficiently large swap file (let's say, 40MBytes) from the Windows' Control Panel.

You should also make sure the .PIF file for your program doesn't have too low limit on EMS/XMS usage (better make them both -1). What's that? You don't have a .PIF file for this program? Then Windows uses the default DOSPROMPT.PIF, which almost surely defines very low limits on these two, and your program can't get the memory it needs for its stack.

| Previous | Next | Up |

16. Command-line Arguments Handling in DJGPP

DJGPP handles command-line argument differently from most DOS-based compilers, to make it closer to Unix platforms (so that porting of Unix programs will be easier). This chapter answers some questions about this aspect of DJGPP.

| Previous | Next | Up | Top |

16.1 Filename wildcards expansion under DJGPP

Q: Can I do filename globbing with DJGPP?

Q: I call my program with an argument x*y and it complains about something called xyzzy??...


A : The filename globbing in DJGPP is done by the start-up code, before your main function is called. Unlike other DOS-based compilers, where you must link your program with a special object module if you want the program to get expanded filenames, in DJGPP this is considered normal behavior and performed by default on behalf of every DJGPP program. The x*y above was expanded to a file called xyzzy which was probably present in the current working directory. (If you don't want the default expansion, see how to disable globbing.)

In DJGPP, filename globbing works like in Unix, which is more general than the usual DOS wildcard expansion. It understands the following constructs with special meta-characters:

?
any single character.
*
zero or more arbitrary characters, including a dot `.'
[aA_]
any one of characters `a', `A', or `_'.
[a-d]
any one of characters `a', `b', `c', or `d'.
[!a-z]
anything but a lowercase letter.
...
all the subdirectories, recursively (VMS aficionados, rejoice!).
.../*
all the files in all subdirectories, recursively.
Unlike DOS, the * and ? meta-characters can appear anywhere in the filename pattern, like in [a-z]*[0-9].*pp. You can also use * instead of directories, like in */*/*.c, but not on drive letters (e.g., [a-c]:/ won't work).

An argument which cannot be expanded (no filenames matching that particular pattern) will be passed to the program verbatim. This is different from what you might see under Unix, where some shells (like csh) would say something like "No match" and won't call your program at all. DJGPP's behavior in this case is like shells of the Bourne legacy (sh, ksh, and bash).

| Previous | Next | Up | Top |

16.2 How to disable filename wildcards expansion

Q: OK, but I don't want my program to glob its arguments (they aren't files at all, but they include characters like * and ?). What should I do?


A : You have these alternatives:

| Previous | Next | Up | Top |

16.3 How to pass command-line arguments with quotes or @

Q: I have a file with a single quote in its name, but the quote seems to be stripped away when I pass it to my program ...

Q: How do I pass a command-line argument which contains double quotes?

Q: How do I pass an argument which begins with the @ character?


A : This is because usually, the command-line arguments are expanded ("globbed") before they are passed to main (see description of filename expansion), and the quote characters serve to protect the arguments from expansion. You should escape-protect the quote characters with a backslash. For example, if you have a file called myfile.c'v, type it as myfile.c\'v when you call your program. If you have single quotes in your program arguments and you don't want those arguments to be expanded, then surround them by double quotes, like this: "*.c\'v". The program will get the string *.c'v with the double quotes stripped away.

Note that backslashes are only special if they are in front of a quote, whitespace, or backslash (they also serve as DOS directory separators, remember?).

The @ character serves to signal a response file (see the description of response file method), so it's also special. To pass an argument whose first character is @, surround that argument with single or double quotes, otherwise it will be taken as a name of a response file which holds the actual command line.

| Previous | Next | Up | Top |

16.4 How to pass command lines longer than 126 characters

Q: Can I invoke my program with a command line longer than the infamous DOS 126-character limit?

Q: I have a Makefile of Unix origin which contains some very long command lines. Will it work with DJGPP?


A : Yes and yes. DJGPP supports several methods of passing command-line arguments which allow to work around the DOS 126-character limit. These are: Of course, if the start-up code doesn't see any of the above methods, it will use the command line by default.

| Previous | Next | Up | Top |

16.5 What is the maximum length of command line under DJGPP

Q: What is the longest command line I can pass to gcc when it is invoked by Make?


A : The arguments are passed to DOS Exec call (Int 21h function 4Bh) via the transfer buffer which is 16KB-long. Apart of the command line, it is also used to pass other info, such as the !proxy parameters and the copy of the environment for the child program (let's say, less than 2000 bytes in most cases, but your mileage may vary). This leaves at least 13K bytes for arguments (including a separating blank between any two arguments). So unless your arguments span more than 160 screen lines, you shouldn't worry.

This limit depends on the size of the transfer buffer, so check how large is the value recorded in the stub header of any program before you pass it extremely long command lines. The linker (ld.exe) is the first program you should worry about, because it usually gets long command lines (they include the list of all the object files and libraries to be linked).

| Previous | Up | Top |

16.6 Why Make passes only 126 characters to programs?

Q: I use Make to compile with GCC, but GCC gets only the first 126 characters of its command line. Didn't you just explain in so many words that invoking a DJGPP program (GCC) from another DJGPP program (Make) can safely pass up to 13K characters of command-line arguments using the !proxy method?


A : Check your Makefile for SHELL = command.com statements, or for commands which include pipe or redirection characters like >, |, etc. If Make sees any such statements, it will invoke COMMAND.COM to run GCC, and COMMAND.COM can't pass more than 126 characters to GCC. To work around, comment-out the SHELL= line, and change your commands to work without redirection/pipe characters.

| Previous | Next | Up |

17. Converting DOS Programs/Libraries to DJGPP

If you have a program or a library developed under some other DOS-based compiler, which you want to port to DJGPP, read this chapter.

| Previous | Next | Up | Top |

17.1 GCC/Gas won't accept valid assembly code ...

Q: I have some code written in assembly which compiles under MASM and TASM, but GCC gives me a long list of error messages.


A : The GNU Assembler (as.exe), or Gas, called by GCC accepts AT&T syntax which is different from Intel syntax. Notable differences between the two syntaxes are: Examples:

         Intel:  [ebp - 4]         AT&T:  -4(%ebp)
         Intel:  [foo + eax*4]     AT&T:  foo(,%eax,4)
         Intel:  [foo]             AT&T:  foo(,1)
         Intel:  gs:foo            AT&T:  %gs:foo

For a complete description of the differences, get and unzip the files named as.iN (where N is a digit) from the bnu252b.zip archive, then See the "i386-Dependent" section of the "GNU assembler documentation". If you don't read this FAQ with an Info browser, type at the DOS prompt:

      info as machine i386

You will see a menu of Gas features specific to x86 architecture.

| Previous | Next | Up | Top |

17.2 Double-check code produced by Gas

Q: My assembly code gets corrupted by Gas!


A : When writing assembly code, you should remember to not trust Gas! You should always check that it does what you expect it to do. GNU Assembler can currently be trusted only when it assembles code produced by GCC. All other code--yours--is subject to introduction of subtle errors. To be sure, use a debugger to check the code (even objdump from GNU Binutils doesn't always treat segment overrides correctly). The following lists some guidelines for safer machine-language programming with Gas:
  1. Use explicit sizing. E.g., use movl instead of mov, even if you're sure the arguments are 32-bit wide. The fact that you use byte registers doesn't seem to matter with Gas.
  2. Write code segment overrides as .byte constants, not as e.g. %cs:. According to Charles Sandmann, Gas uses the current phase of the moon in deciding whether to ignore your prefixes. So unless you know exactly what is the phase of the moon at the moment of assembly, use .byte constants.
  3. Make sure the operands match the instructions. Don't assume that if they don't, you'll get an error message from the assembler.

| Previous | Next | Up | Top |

17.3 Converting Intel ASM syntax to AT&T syntax

Q: Where can I find an automated conversion tool to convert my Intel-style assembly code into a code acceptable by Gas?


A : A Sed script which should do most of the conversion was posted to the DJGPP newsgroup in the past. You can find it in the DJGPP archives. A conversion program called TA2AS which can convert TASM assembly source to the AT&T format, can be found on OULU repository and on the DJGPP server. TA2AS was written by Jan Oonk. Alternatively, here is what you can do to convert your code:

Note: If you use MASM or LIB32, please post your experiences to the comp.os.msdos.djgpp, so that I could make the above instructions less vague.

Keep in mind that syntax is only one of the aspects of converting code written for DOS to DJGPP. You should also make sure your code doesn't violate any rules for protected-mode programming (see next question).

| Previous | Next | Up | Top |

17.4 Converted code GP Faults!

Q: OK, I've succeeded to convert and compile my assembly-language program, but when I run it, I get "Segmentation Violation" and "General Protection Fault". This program works when compiled with MASM, so how can it be?


A : In DJGPP, your program runs in protected mode. There are certain things you can't do in protected-mode programs (that's why it is called protected mode). This issue is too complex to describe here, so only a few of the more important aspects will be briefly mentioned. If you are serious about writing assembly language protected-mode code, or have a large body of existing code to convert to protected mode, you should read any of the books about protected-mode programming with 80x86 processors.

Here is a short list of some of the techniques found in many real-mode programs, which will trigger protection violation or erratic behavior in protected mode:

| Previous | Next | Up | Top |

17.5 I want to use a .obj or .lib code with DJGPP

Q: I have a set of useful functions in a .obj format, but no source code. Can I use them with my DJGPP program?

Q: I have this ACMELUXE.LIB library of functions which I want to use. I've extracted all the .obj files, but when I try to link them with my program, GCC complains: "File format not recognized". Can't I use these object files?

Q: I've got a bunch of .obj files I want to use. I've ran AR to make a GCC-style .a object library, but got an error message from GCC saying "couldn't read symbols: No symbols". How can I link them with my code?


A : Sorry, you probably can't. The GNU linker called by GCC doesn't understand the format of .obj files which other DOS-based compilers/assemblers emit. Unless you can get the source of those functions, convert it to protected-mode, flat-address model code and compile them with GCC, you most probably won't be able to use them. Lately, an automated conversion tool called OBJ2COFF was written by Jan Oonk which can be used to convert .obj object files and .lib libraries to COFF format, provided that the original .obj files must have been written for flat-address memory model. (You can also try using LIB32 librarian from Microsoft C8 to convert object files to COFF.) The main problem, of course, is that most such object files were written for real-mode programs in memory models other than flat, and without extensive modifications would crash your program anyway... (See previous question.)

OBJ2COFF is available from the OULU repository and from the DJ Delorie's ftp server.

| Previous | Up | Top |

17.6 I must use my 16-bit code with DJGPP!!

Q: If that's how it is, then I would have to give up using DJGPP. I simply cannot live without these .obj files. Are you really sure there is nothing I can do??


A : If you need your old code that bad, then there might be a way, albeit a cumbersome one. You can write a 16-bit, real-mode program and link it with your precious functions you can't live without. Have this program spawn a DJGPP-compiled program and make the two communicate with each other via a buffer allocated in low memory, or via command-line parameters passed to the 32-bit program by the spawnXX function call. You can also call 16-bit functions directly with the library function called __dpmi_simulate_real_mode_procedure_retf, provided the 16-bit program passes the CS:IP values of these functions to the 32-bit program. You can even put your 16-bit code as binary instructions into a buffer allocated in low memory and call it with __dpmi_simulate_real_mode_procedure_retf (but if you can do that, you probably can also disassembly the code into a source form and submit it to Gas).

Now will you consider to stick with DJGPP? Please??...

| Previous | Next | Up |

18. Low-level DOS/BIOS and Hardware-oriented Programming

This chapter sheds some light on a few aspects of writing DJGPP programs which interact with hardware or use interrupts.

| Previous | Next | Up | Top |

18.1 Got "Unsupported INT 0xNN" calling int86

Q: Why does my program crash with "Unsupported DOS request 0xNN" or "Unsupported INT 0xNN" when I call int86 or intdos functions to invoke a software interrupt?


A : Calling real-mode DOS or BIOS services from protected-mode program requires a switch to real mode, so int86 family of functions in the DJGPP library should reissue the INT instruction after the mode switch. However, some services require pointers to memory buffers. Real-mode DOS/BIOS functions can only access buffers in conventional memory, so int86 has to move data between your program and low memory to transparently support these services. But this means it should know about all these services to perform these chores correctly, because each service has its own layout and size of the buffer(s). While int86 supports many of these services, it doesn't support all of them. The supported functions are listed in the library reference. See the "int86" section of the "libc.a reference". For those it doesn't support, you will have to call the __dpmi_int library function instead. It is also documented in the library reference, See the "__dpmi_int" section of the "libc.a reference". __dpmi_int requires that you set up all the data as required by the service you are calling, including moving the data to and from low memory (See how to use buffers with DOS/BIOS services, below).

| Previous | Next | Up | Top |

18.2 How to use buffers with DOS/BIOS services

Q: I want to call a DOS/BIOS function which requires a pointer to a buffer in, e.g. ES:DI (or any other) register pair. How do I get the segment to put into the ES register?


A : If you use int86x or intdosx for a DOS or BIOS function supported by them, then just put the address of your buffer into the register which expects the offset ( regs.x.di ) and forget about the segment. These functions are processed specially by the library, which will take care of the rest.

If you call __dpmi_int, then you must put into that register pair an address of some buffer in conventional memory (in the first 1 MByte). If the size of that buffer doesn't have to be larger than the size of transfer buffer used by DJGPP (16KB by default), then the easiest way is to use the transfer buffer. (Library functions don't assume its contents to be preserved across function calls, so you can use it freely.) That buffer is used for all DOS/BIOS services supported by DJGPP, and it resides in conventional memory. DJGPP makes the address and the size of the transfer buffer available for you in the _go32_info_block external variable, which is documented the library reference. Check the size of the buffer (usually, 16K bytes), and if it suits you, use its linear address this way:


     dpmi_regs.x.di =
      _go32_info_block.linear_address_of_transfer_buffer & 0x0f;
     dpmi_regs.x.es =
      (_go32_info_block.linear_address_of_transfer_buffer >> 4) & 0xffff;

For your convenience, the header file defines a macro __tb which is an alias for _go32_info_block.linear_address_of_transfer_buffer .

If the size of the transfer buffer isn't enough, you will have to allocate your own buffer in conventional memory with a call to the __dpmi_allocate_dos_memory library function. It returns you the segment of the allocated block (the offset is zero). If you only need a small number of such buffers which can be allocated once, then you don't have to worry about freeing them: they will be freed by DOS when your program calls exit .

For bullet-proof code, you should test the size of the transfer buffer at runtime and act accordingly. This is because its size can be changed by the STUBEDIT program without your knowledge.

| Previous | Next | Up | Top |

18.3 How to call software interrupt functions

Q: My program crashes/doesn't do what it should when I call __dpmi_simulate_real_mode_interrupt .


A : You should zero out some of the fields of the __dpmi_regs structure before you call that function. Random values in these fields can cause your program to behave erratically. The fields in point are SS, SP and FLAGS. When SS and SP are zeroed, the DPMI host will provide a stack for the interrupt handler which is at least 30-word long (most DPMI hosts provide much larger stack); this is usually enough, but if it isn't, then you should point SS and SP to a larger buffer in conventional memory (possibly part of the transfer buffer).

If SS:SP isn't zero, they will be used as the address of the stack you want to be used by the interrupt handler, so if they have random values, your program will crash. A non-zero FLAGS field can also make the processor do all kinds of weird things (e.g., imagine that the single-step or the debug bit is set!).

If you don't have any reason to set SS:SP to your stack, it's easier to call __dpmi_int library function, which zeroes out the stack pointer and the FLAGS fields for you (and also doesn't force you to type long names!).

| Previous | Next | Up | Top |

18.4 How to move data between your program and conventional memory?

Q: How can I move data between my program and the transfer buffer?

Q: How do I access my peripheral card which is memory-mapped to an address between 640K and 1M?

Q: How can I read or change a value of one of the variables in the BIOS data area?

Q: How can I peek at an address whose far pointer I get from an INT 21h call?


A : Depending on your specific needs, you can use one of three methods:

| Previous | Next | Up | Top |

18.5 Conventional-memory addresses use only 20 bits

Q: I call movedata to pass data between my program and the transfer buffer, but get bogus values or General Protection Fault.


A : Valid conventional-memory addresses are only 20 bit-wide. However, the value stored in the variable _go32_info_block.linear_address_of_transfer_buffer (or its alias, __tb ) is not guaranteed to have the higher 12 bits zeroed, and movedata doesn't mask those high bits, because it can also be used to move data between 2 protected-memory locations. Be sure to mask off the high 12 bits of the value returned by various ..._linear_address_... fields in DJGPP structures, whenever that address references a conventional memory location, before you call any of the functions from the movedataX family, the "farptr" or the "nearptr" functions.

| Previous | Next | Up | Top |

18.6 Fast access to memory-mapped devices or absolute addresses

Q: The "farptr" functions are too slow for my application which MUST have direct access to a memory-mapped device under DPMI. How can I have this in DJGPP? My entire optimized graphics library is at stake if I can't! :(


A : The following so-called Fat DS method was suggested by Junaid A. Walker (he also posted a program which uses this technique to access the video RAM; you can look it up by searching the mailing list archives). But first, a word of warning: the method I'm about to describe effectively disables memory protection, and so might do all kinds of damage if used by a program with a wild pointer. Or, as Stephen Turnbull has put it:
Surgeon General's WARNING: The description below uses the "Fat DS hack", a steroid derivative which gives your program great strength, a thick neck, baldness, and is known to be closely linked with the Alzheimer's disease.

Having said that, here is the trick: you change the limit of the segment descriptor stored in DS to 0xffffffff (i.e., -1), using function 8 of the DPMI interrupt 31h. After that, you have access to all the memory which is currently mapped in. You then use the 32-bit wrap-around in the linear address space to access memory at, say, linear address 0xa0000 (which belongs to the VGA), or any other address on your memory-mapped device. You should know up front that this trick won't work with every DPMI host, and some events break this scheme even for those DPMI hosts which will silently allow you to set such a huge limit on the memory segment. CWSDPMI, QDPMI, Win 3.x all allow this; Linux's DOSEMU and, probably, OS/2 Warp don't. A call to malloc or any other library function which calls sbrk might sometimes change the base address of DS selector and break this method unless the base address is recomputed after sbrk call. (The "nearptr" functions support this recomputation by providing you with the __djgpp_conventional_base variable, but it is your responsibility to use it.) The same change happens when you call system, and as result of some other events external to the executing code thread, like multitasking or debugger execution.

If you are aware of these limitations, and don't need your code to run under all DPMI hosts, it might be the fix to your problems.

Confused about how exactly should you go about using this technique in your program? Look at the docs of the "nearptr" functions, See the "__djgpp_nearptr_enable" section of the "libc.a reference".

| Previous | Next | Up | Top |

18.7 Accessing absolute address above 1MB

Q: How can I access a memory-mapped peripheral devices (or any other absolute address) above 1 MByte mark?


A : Use the __dpmi_physical_address_mapping library function. It returns a linear address which can be used to access a given absolute physical address. You can then use the functions from to access that linear address. Specifically, these are the DPMI calls that you will have to use: All of these DPMI calls have __dpmi__XXX wrappers in the DJGPP library.

| Previous | Next | Up | Top |

18.8 How to make DOS/BIOS call your function

Q: How can I make any real-mode service call my function? E.g., the mouse driver has a provision (function 0Ch) to call user-defined handler when certain events occur, which expects a far pointer to my function in ES:DX register pair.


A : Those services expect a real-mode function, so you should wrap your protected-mode function with a real-mode stub. To this end, call either the _go32_dpmi_allocate_real_mode_callback_retf or the _go32_dpmi_allocate_real_mode_callback_iret library function, as required by the real-mode service you want to hook, and pass the `segment' and `offset' fields it returns to the service you want (in the above example, Int 33h function 0Ch) by calling __dpmi_int . See the docs in the library reference Info file for further details about allocating wrapper function.

| Previous | Next | Up | Top |

18.9 How to hook hardware interrupts

Q: How do I register my DJGPP function as a hardware interrupt handler?


A : The optimal set-up depends on the interrupt frequency and on the amount of processing it requires. Therefore, only some basic considerations and techniques are listed below. What combination of these is best for your application is up to you to decide.

First, some background. Hardware interrupts can occur when the processor is either in real mode (like when your program calls some DOS service) or in protected mode. When your program runs under a DPMI host, hardware interrupts are always passed to protected mode first, and only if unhandled, they are reflected to real mode. Therefore, in DPMI mode you can get away with installing only a protected-mode handler. However, if the interrupts happen at a high frequency (say, more than 10 KHz), then the overhead of the interrupt reflection from real to protected mode might be too painful, and you might consider installing a real-mode interrupt handler in addition to the protected-mode one. If you do, you must hook the PM interrupt first, then the RM one (because hooking the PM interrupt modifies the RM one). Also, you should know that some DPMI hosts don't allow you to hook the RM interrupt (CWSDPMI does); the only way to be sure is to try.

To install a protected-mode interrupt handler, you do this:

To install a real-mode interrupt handler, you do this:

For examples of installing and using hardware interrupt handlers, see the files sb05_dj2.zip (Sound Blaster interrupt-driven functions) (also available on OULU repository).

| Previous | Next | Up | Top |

18.10 Hardware interrupt hooking has its subtleties ...

Q: I did all the above, but my program occasionally still hangs...


A : Hooking hardware interrupt in DJGPP (and in protected mode in general) has a few subtle aspects. In general, hardware interrupt handling in DJGPP v2.0 is rock solid if you play by the rules. Unfortunately, the rules are a bit tricky.

One cause of your problems might be that your interrupt handler or some memory location it uses get paged out because of the virtual memory mechanism, or because your program spawned a child program. In that case, the interrupt might cause a call to a non-existent service routine, with the obvious results. You should lock all the memory pages that your handler accesses by calling the __dpmi_lock_linear_region library function. This also means in practice that you should write your handler in assembly, as described in how to set an interrupt handler, above. You can disable virtual memory, or put _CRT0_FLAG_LOCK_MEMORY into _crt0_startup_flags to make sure nothing is paged out (but then your program might not have enough memory to run, unless you run on memory-abundant system).

Another problem might be that the hardware peripheral you use generates a lot of interrupts. Due to specifics of hardware interrupts handling in protected mode, there is a substantial overhead involved with reflection of interrupts between real and protected modes. For instance, on a 486DX/33 this reflection might consume up to 3000 clocks; on a 386SX/16, even a 1KHz clock might eat up 1/2 of available cycles. If your hardware fires too much interrupts, your CPU might not be able to keep up. In that case, consider reducing the interrupt frequency, or move some of the processing done inside interrupt handler to some other place. If your handler is written in C, write it in assembly and make sure it doesn't chain. If that doesn't help, install a real-mode handler.

Some losing memory managers, notably EMM386, were reported to induce a high interrupt handling overhead. In one case, a user reported an increase in the interrupt rate from 2 KHz to 6 KHz after uninstalling EMM386.

Still another possibility is that you use a non-default sbrk algorithm in your program (check if the header file crt0.h is included anywhere in the program, and if so, is the _CRT0_FLAG_UNIX_SBRK bit in the _crt0_startup_flags variable set by the program. If it is, then a hardware interrupt which happens at the wrong time could crash your machine, especially if you run under Windows 3.x. If the above still doesn't explain your problem, then post your code on the comp.os.msdos.djgpp or the djgpp mailing list, tell us how does it fail and somebody will usually have a solution for you.

| Previous | Up | Top |

18.11 How to read and write ports

Q: I need to read from and write to PC ports, and I'm accustomed to using the inp and outp functions. But I hear they aren't available in DJGPP?


A : They are in v2.x. Just #include <pc.h> and you get their prototypes. The functions themselves are in the default library. Note that there are also size-specific versions for byte- word- and dword-long access (e.g., inportl for reading a 32-bit dword), as well as functions to read/write sequences of bytes and words, like inportsb and outportsw; these are DJGPP-specific.

| Previous | Next | Up |

19. Legal Aspects

This chapter answers some questions about various legal aspects of writing programs with DJGPP.

| Previous | Next | Up | Top |

19.1 Legal (un)restrictions on DJGPP applications

Q: Can you explain in plain English the legal restrictions of distributing programs compiled with DJGPP?

Q: Can I write commercial programs with DJGPP?


A : In most cases, you don't have to worry. Using the GNU C/C++ compiler to compile your programs doesn't make your programs subject to any restrictions. The C library which comes with DJGPP is free , which means you are free to use it in every way you like (but please observe basic rules of courtesy.) So, if you write C programs, you have absolutely nothing to worry about. The basic C++ iostream class library (libiostr.a) which comes with DJGPP allows you to use it binary-wise (i.e., without changing library sources) in your C++ programs without restrictions , unless you compile your programs with a compiler other than Gcc (which won't happen if you work with DJGPP). The library of additional C++ classes (libgpp.a) also allows you to link it freely with your applications, but requires that you provide your customers with source or object code of the application, so they could relink the application with future or modified versions of the C++ library. (If you intend to distribute commercial programs linked with the libgpp.a library, you are strongly advised to read the GNU Library General Public License which comes with the library, for rigorous definition of its terms.)

Note that libiostream.a library is special in that it doesn't place your program under GPL or LGPL, so if you only use C++ classes included in that library, make your compilations use it instead of libgpp.a. (That's the only reason of having libiostream.a as a separate file, because libgpp.a includes everything libiostream.a does, so you never need both of them.)

Two GNU packages, Flex and Bison, are also special in that using them to produce your programs doesn't place your programs under GPL or LGPL. In other words, lexers produced by Flex and parsers produced by Bison do not imply GPL/LGPL.

If you do use in your program any of the FSF sources that fall under GPL/LGPL (like some of the GCC's sources, or the GNU getopt or regex packages which come with many GNU programs), then you must comply with the terms of GNU licenses when distributing your programs; in this case your entire application becomes GPL. If that is unacceptable to you, consider using the versions of regex and getopt from the DJGPP C library (which is free).

You may ship any of the utilities developed specifically for DJGPP (e.g., the floating-point emulator or the CWSDPMI DPMI host) as distributed by DJ Delorie with your program with no other requirement besides telling your customers how to get DJGPP for themselves.

| Previous | Up | Top |

19.2 Legal restrictions of DJGPP utilities and libraries

Q: Can I redistribute djgpp, and if so, how?

Q: I run a business that sells shareware for distribution costs. Can I include djgpp on my CD-ROM?

Q: I want to include djgpp in a product that happens to need a compiler provided with it. Can I do this?

Q: Is DJGPP GNU software?

Q: Is DJGPP public domain software?

Q: Is DJGPP shareware?


A : DJGPP is not public domain, neither is it shareware (you don't have to pay a license fee to use DJGPP). Parts of DJGPP (the compiler and some of the development tools) are GNU software, so you must comply with GNU GPL if you distribute those parts (usually, you won't need to distribute them, because they are freely available to everyone). A small part of the C library is taken from the Berkeley BSD sources, and is therefore in public domain. Other parts of DJGPP, which includes most of the C library, the free DPMI host CWSDPMI, and some of the utilities are copyrighted, but in a way that allows you to use them freely and without restrictions.

When you redistribute parts of DJGPP itself (as opposed to your programs compiled with DJGPP), you must comply to the conditions applicable to whatever you distribute. The parts which are in public domain are, of course freely distributable. Other parts of DJGPP fall under the DJGPP copyright which allows you to redistribute everything provided you follow these rules:

In addition, it would be a courtesy to inform DJ Delorie that you are including DJGPP in your product, in case this information is obsolete. A token sample of your distribution would be nice also.

| Previous | Next | Up |

20. Getting Help

This chapter tells you how to get answers to questions you didn't find in this FAQ.

| Previous | Next | Up | Top |

20.1 Don't post DJGPP-specific problems to GNU Newsgroups

Q: I post my problem to the "help-gcc" Newsgroup, but don't get any answers.


A : Is your problem likely to be special to the DJGPP port or to DOS environment? If so, don't post to GNU Usenet groups, but to the comp.os.msdos.djgpp or to the DJGPP mailing list. People who read GNU Newsgroups usually neither know nor care about DOS-specific problems. Post there only if the problem seems to be a generic one in one of the FSF utilities. For most problems, this can be deduced only after either tracing a problem in the source code or testing it on some non-DOS platform. As a general rule, always post to DJGPP group first.

| Previous | Next | Up | Top |

20.2 How to post to the mailing list

Q: How do I post to the DJGPP mailing list?


A : Send mail to the list address as if it were a person. Please use the mailing list only if you cannot access the DJGPP Newsgroup, because reflecting the mail to and from the mailing lists incurs additional load on the DJGPP server.

| Previous | Next | Up | Top |

20.3 How to become a subscriber to the mailing list

Q: How do I subscribe to DJGPP mailing list?


A : Send mail to the list server (NOT to djgpp@!!), leave the subject line empty and in the body write:
subscribe djgpp
If you only want to receive announcements of new versions and ported software, but don't want to see any other DJGPP mail traffic, subscribe to djgpp-announce mailing list:
subscribe djgpp-announce
The announcements which go to djgpp-announce get reflected to djgpp, so you don't have to subscribe to both these lists.

The DJGPP mailing list is available in the daily and weekly digest forms. To subscribe to one of these, send this one-line message to the above list server:

subscribe djgpp-digest-daily
or
subscribe djgpp-digest-weekly
You can also subscribe to DJGPP-related mailing lists through DJ Delorie's WWW server.

Note that you don't have to subscribe to djgpp mailing list if you don't want to get all the traffic in your mailbox (typically, about 30 messages per day). You can ask questions on the list even if you are not a subscriber, because people usually answer both to your e-mail address and to the list (well, actually, the mailer program does it automatically and most people don't bother to change that). If you want to be sure the mail gets to you directly, say in your message that you don't subscribe to the list, and ask people to answer directly.

If you have a Usenet feed, consider reading the comp.os.msdos.djgpp instead, so that the load on the DJ's list server will get lower. There is also a possibility of reading the Newsgroup (but not posting to it) through the Mercury Gopher server at Michigan State University

| Previous | Next | Up | Top |

20.4 How to unsubscribe from the mailing list

Q: Whew! There's too much traffic on djgpp mailing list (at least the SysAdmin glaring over my shoulder thinks so... ;-). How do I unsubscribe myself?

Q: I've been trying for days to unsubscribe from the djgpp mailing list. What am I doing wrong?


A : You should be sending your unsubscribe messages to the list server (not djgpp@delorie.com!), with the contents being just this:
unsubscribe djgpp
If you have done that and it didn't help, write to the DJ Delorie and ask him to help you.

You can also unsubscribe yourself from any of the DJGPP-related mailing lists through DJ Delorie's WWW server.

| Previous | Next | Up | Top |

20.5 If you don't see any message from the list ...

Q: I don't get any messages from DJGPP list for several days. Is the list alive?


A : Try sending a message to the list and see if you get it back. If not, it is possible that your name was inadvertently taken off the list. This is known to happen sometimes (don't ask me how). You can check if you are subscribed to any of the DJGPP-related mailing lists through DJ Delorie's WWW server. If this tells you you're not, re-subscribe yourself by sending the above subscription message to listserv, or via DJ's server. When in doubt, re-subscribe anyway (it doesn't hurt neither you, nor the list server).

| Previous | Next | Up | Top |

20.6 Why do I get every message more than once?

Q: Why am I getting 2 and often more copies of the same message? Don't you people think I can get the idea at the first reading??


A : First, check the headers to make sure that all of the duplicate messages have their To: header addressed to the DJGPP list, not to your direct e-mail address. Often, when people reply to your post, you get the direct message, and a Cc: (the carbon copy) one via djgpp list server. This is normal behavior.

If indeed you get more than one copy of a message addressed to the list, it is possible that you have added yourself to the list several times. (This could happen if your site supports a mail exploder which re-mails DJGPP to you, and you also have subscribed yourself directly.) One way to check this would be to unsubscribe and see if you keep getting mail. Another way is to check your subscription through DJ's server. Look out for multiple subscriptions, possibly under different names/addresses. You could also write to a DJ Delorie, and ask him to investigate.

Another thing to do, especially if you think it's not your fault, is to write to a user named POSTMASTER at the address of each of the machines whose names you find in the Received: headers of the bouncing messages (these are people responsible for the operation of the mail software at their sites) and ask them politely to help.

Many times this kind of problems is caused by excessive load on the list server, so everybody who can, please switch to reading the comp.os.msdos.djgpp and unsubscribe from the list.

| Previous | Up | Top |

20.7 DJGPP now has a Newsgroup!

Q: With so much daily traffic (about 30 messages a day), isn't it high time to create a Newsgroup?


A : Beginning June 1st, 1995, DJGPP has its Newsgroup! It is called comp.os.msdos.djgpp, and it is two-way gated to the venerable DJGPP mailing list. This means messages posted to either the mailing list or the newsgroup will appear on both (once, let's hope ;-) ; you can read either one and post to either one, and everyone eventually sees everything. The entire traffic ends up in the mail archives on the DJ's Web server within 24 hours, and is available for searching. If you have a Usenet feed, now is the time to consider unsubscribing from the mailing list and switch to reading the Newsgroup instead, so that the load on the list server will get lower.

| Previous | Next | Up |

21. Version 2.0 vs v1.x

This chapter is for those who are used to working with DJGPP v1.x and want to more about v2.0 while they consider to switch.

| Previous | Next | Up | Top |

21.1 New features in DJGPP v2.0

Q: What exciting new features will I find in v2.0 as opposed to v1.x?


A : DJGPP v2.0 is a DPMI-only environment, and it includes a free DPMI host for those who don't have other DPMI provider installed. In addition, v2.0 features the following major improvements upon v1.1x:

If you want to help in further v2.0 development, check out the list of features which have yet to be done and volunteer to implement some of them.

| Previous | Up | Top |

21.2 DJGPP environment in v2.0

Q: There's been this talk about v2.0 and about go32 going away in that version, but I'm confused on what the new setup will be. Could you clarify the details of this change?


A : In v1.x of DJGPP, the go32 extender was responsible for the following: In v2.x, most of these functions are done by a DPMI host, which is a memory-resident software required to run protected-mode programs under MS-DOS. There are a few commercial DPMI hosts (like Quarterdeck's QDPMI, Qualitas 386Max, MS-Windows 3.x and Win95, OS/2, even Linux), but DJGPP v2.0 comes with a free DPMI host called CWSDPMI for those who don't have one already. Loading the application into protected-mode memory (a function done in v1.x by go32) is handled by a 2KB-long real-mode stub which runs at start-up, before the application's main functions us called (the stub will also load CWSDPMI if no other DPMI host is detected). All the other custom code required to process BIOS- and DOS-related calls from protected-mode is now built into the library functions which your program calls, so there is no need for a special extender, because the application just issues DPMI calls serviced by the DPMI host.

CWSDPMI can be loaded as a TSR, even loaded HIGH into the HMA/UMB, which will make the applications load much faster.

| Previous | Next | Up |

22. Miscellany

This chapter is a hodgepodge of questions which don't belong to any of the other chapters.

| Previous | Next | Up | Top |

22.1 How to change a DJGPP package?

Q: I want to change cc1. How do I do this?

Q: How do I fix a bug/add a feature to one of the DJGPP programs?


A : First, get the sources. These are called *s.zip in the DJGPP distribution. The C Library sources are in djlsr200.zip. Some sources are too big, and might be split into multiple zips, all of which must be unzipped to get a complete source distribution, like this:
gcc263s1.zip
gcc263s2.zip
gcc263s3.zip
gcc263s4.zip
gcc263s5.zip
gcc263s6.zip

All sources are shipped in ready-to-build form. The diffs in the diffs/ directory have already been applied.

Next, try to build the program without changing it. Some packages will have a CONFIGUR.BAT file; if so, run it first. If there is a MAKE.BAT file, run it; if not, look for a file named MAKEFILE.DJ or MAKEFILE.DJG; sometimes these will be in a subdirectory called dos/, or msdos/, or pc/. If there is such a file, then type, e.g., make -f makefile.djg, if not, just say make and see what happens. (The reason for an apparent lack of a standards here is that different packages were ported to DJGPP by different people, as best as they saw fit.) After you've succeeded to build the program, make your fixes and build the program the same way you did before.

Note that generally you must have GNU Make program to build these programs (get the file mak373b.zip), and some makefiles require that you install additional utilities, like Sed (get sed118b.zip). Sometimes the makefiles won't even run under COMMAND.COM (they require a smarter shell). In that case, either get a better shell, convert the makefile to be runnable by COMMAND, or do the required steps manually. If the Makefile is too complex for you and you can't figure out what are the necessary commands, invoke make with -n switch and see what it would have done. If your machine lacks floating-point hardware (like a 386 without a 387, or a 486SX), then you should know that current versions of GNU Sed and GNU Make issue floating point instructions, so you will have to make provisions for loading an emulator, see above, FP Emulation.

| Previous | Next | Up | Top |

22.2 Where to find sample DJGPP code or a package ported to DJGPP?

Q: Where can I find an example of XXXX / a package doing YYYY ?


A : Stephen Turnbull has compiled a list of publicly available packages related to DJGPP, based on the DJGPP mailing list traffic. The list is still under construction (Steve says that many pointers have not been followed up to get host and directory references right), so this list must be taken with a grain of salt. Check out Steve's list.

Here is a short list of places you might look into for examples of frequently needed code fragments, or for packages people keep asking about:

| Previous | Next | Up | Top |

22.3 How to create symbolic links to programs

Q: How do I create symbolic links?

Q: I have this program that behaves differently depending on the name it's called. Under Unix, I just create symbolic links to achieve that, but DOS doesn't support links. Do I have to put several identical programs under different names on my disk??


A : DJGPP allows you to simulate symbolic links to programs. Generate a stub (which is a small DOS program attached to every DJGPP program by the stubify.exe program), call it by the name of the link you want, then edit its header to run another program. For example, let's say the real program is dj1.exe and we want to make a link called dj2.exe that really calls dj1.exe. First, generate a stub under the name dj2.exe. Next, run STUBEDIT to modify the new programs' stub info block to change the name of the executable it runs. In this case, we'd change it to dj1:

      C:\USR\BIN> stubify -g dj2.exe
      C:\USR\BIN> stubedit dj2.exe runfile=dj1

Voila! Now, when you run dj2, it tells the stub to load the image of dj1, but pass "dj2" in argv[0] .

| Previous | Next | Up | Top |

22.4 Where to find the DPMI specification?

Q: Where can I find the specifications for the DPMI functions?


A : You can find the DPMI 0.9 spec by anonymous ftp to one of the following sites:

At Quarterdeck ftp site.

At the OULU repository of PC-specific programming info.

The DPMI 1.0 specs are available by anonymous ftp from the Intel anonymous ftp site. (The file dpmiv1p.zip at the same location is the PostScript version of this spec.)

Some information about the DPMI API is also found in the Ralf Brown's Interrupt List. Look at the functions of Interrupt 31h, or search the files for the word DPMI.

| Previous | Next | Up | Top |

22.5 The DJGPP Web site.

Q: Where is the DJGPP Web site?


A : Yes, DJGPP has its own home on the Internet, set up and maintained by (who else?) DJ Delorie. It has an HTML version of this FAQ list with search capabilities, the entire set of DJGPP distribution files, a searchable archive of the DJGPP mailing list traffic, plus other interesting information about DJGPP. For instance, did you ever wondered how DJGPP got started and what were DJ's original goals? Rejoice: the Web site includes the story of DJGPP genesis.

To visit, point your Web browser to the DJGPP Web site.

| Previous | Next | Up | Top |

22.6 Where to upload your contributions to DJGPP

Q: I wrote a program using DJGPP. How can I make it available to others?

Q: I found and corrected a bug in one of the programs distributed with DJGPP. Where should I put it?


A : If the program/patches are small enough, consider posting it to the mailing list or the comp.os.msdos.djgpp as uuencoded compressed archive (to conserve space).

If the compressed file is larger than, say, 50K bytes, it's best to upload it to a public site where everybody can get it. You can upload your contribution to a special directory on the DJ Delorie's FTP server. This directory is write-only, and it gets purged every couple of days, so be sure to write to DJ Delorie about your upload; he will then move it to the /pub/djgpp/contrib directory. (There used to be another place, a directory on omnigate.clarkson.edu which was writable by anonymous, but it was being used for malicious purposes and the sysadmins there decided to close it :-(.)

If you decide to upload, please send mail to djgpp-announce list with a brief description of your program/patch. (The message will get reflected to both the newsgroup and the DJGPP mailing list, so you don't have to cross-post there, but it also goes to people who only subscribe to djgpp-announce list because they only want to get announcements.)

If your program is more than a patch or a beta version, you might consider uploading it to SimTel. If you decide to do it, write to DJ Delorie and ask him for uploading instructions. Material uploaded there gets automatically distributed to all of the SimTel mirrors throughout the world, which makes it easier to get.

| Previous | Next | Up | Top |

22.7 DJGPP as cross-compiler

Q: I want to use DJGPP as a cross-compiler for Motorola 68K targets. How should I proceed about this?

Q: I want to build GCC as a Unix-to-DOS cross-compiler. What should I do?


A : If you want a cross-compiler for m68k on a DOS machine, you need is DJGPP configured as host=i386-go32, and target=m68k-coff. This has been done already. The binaries there are based on GCC 2.6.0.

For building GCC as a Unix-to-DOS cross-compiler, here are the instructions on how to do it. (Unfortunately, "make install" in the Gcc distribution does exactly the wrong thing by default, so you end up copying a lot of stuff around manually.)

Unpack Gcc and Binutils into a directory, let's call it X/. Thus, you have, say, X/gcc-2.7.0 and X/binutils-2.5.2. The following sequence of commands should make the job:


     mkdir $X/dos-binu
     cd $X/dos-binu
      --target=i386-coff-go32
     make CFLAGS=-O
     
     mkdir -p /usr/local/i386-go32-msdos/bin
     
     cd binutils
     cp ar c++filt objcopy objdump size /usr/local/i386-go32-msdos/bin
     cp nm.new /usr/local/i386-go32-msdos/bin/nm
     cp strip.new /usr/local/i386-go32-msdos/bin/strip
     
     cd ../gas
     cp as.new /usr/local/i386-go32-msdos/bin/as
     cp gasp.new /usr/local/i386-go32-msdos/bin/gasp
     
     cd ../ld
     cd ld.new /usr/local/i386-go32-msdos/bin/ld
     
     mkdir $X/dos-gcc
     cd $X/dos-gcc
      --target=i386-go32-msdos
     make LANGUAGES=c CFLAGS=-O
     
     cp xgcc /usr/local/bin/gcc-dos
     cp cc1 /usr/local/i386-go32-msdos/bin/cc1
     cp cccp /usr/local/i386-go32-msdos/bin/cpp

Unzip the DJDev and Gcc distributions in, say, /usr/local/djgpp. Ideally, build libgcc.a on a DOS machine.

Remove all ^M characters from include files (you can compile DTOU.c on the Unix box to make this easier). Alternatively, use the -a switch to UnZip when unzipping the archives.

Change lib/djgpp.lnk to use "coff-i386" instead of "coff-go32" and remove the ^M characters from that file also.


     mkdir -p /usr/local/lib/gcc-lib/i386-go32-msdos/2.7.0
     cd /usr/local/lib/gcc-lib/i386-go32-msdos/2.7.0
     ln -s /usr/local/djgpp/include .
     ln -s /usr/local/djgpp/lib/* .

Build stubify and install it in /usr/local/i386-go32-msdos/bin.

That's it! To build a program for DOS, say something like this:


      gcc-dos hello.c -o hello.exe

| Previous | Next | Up | Top |

22.8 GCC says "garbage at end of number"

Q: There is a severe bug in GCC: it says "garbage at end of number" for this line:


      i = 0xfe+0x20;

Ain't it silly that such a great compiler would fail so miserably?


A : That's not a bug, that's a feature of the ANSI C language definition . By ANSI rules, the above expression is a single preprocessing token, unless you place whitespace in front of the plus sign. The reason for this seemingly counterintuitive feature is the syntax of floating-point constants in which letters `e' and `E' followed immediately by a sign signal a decimal exponent. You can use the -traditional compiler switch to turn this feature off (together with a plethora of other ANSI features; see the GCC docs for details).

| Previous | Up | Top |

22.9 What should sizeof (struct xyzzy) return?

Q: When I call sizeof on a struct, I sometimes get values which are larger than the sum of the sizes of the struct fields, whereas in Borland C++ I always get the correct result. Is it a bug in GCC?


A : No, it's not a bug. GCC generates 32-bit code, and in that mode, there is a significant penalty (in terms of run-time performance) for unaligned accesses, like accessing a 16-bit short which isn't aligned on a word boundary, or accessing a 32-bit int which isn't aligned on a double-word boundary. To produce faster code, GCC pads struct fields so that each field can be accessed without delays; this sometimes produces struct size which is larger than the sum of sizes of its fields. If you need to avoid this padding (e.g., if your program uses large arrays of such structs, where padding will waste a lot of memory), lay out your structures so that the longer fields are before the shorter ones. For example, let's say that you have a struct defined thus:

       struct my_struct {
         char name[7];
         unsigned long offset;
         double quality;
       };

To make such a struct use the least number of bytes, rearrange the fields, like this:

       struct my_struct {
         double quality;
         unsigned long offset;
         char name[7];
       };

If the layout of the structure cannot be changed (e.g., when it must match some external specification, like a block of data returned by some system call), you can use the __attribute__((packed)) extension of GCC (See the "Type Attributes" section of the "GNU C/C++ Manual".) to prevent GCC from padding the structure fields; this will make accesses to some of the fields slower. Beginning from version 2.7.0, GCC has a command-line option -fpack-struct which causes GCC to pack all members of all structs together without any holes, just as if you used __attribute__((packed)) on every struct declaration in the source file you compile with that switch. If you use this switch, be sure that source files which you compile with it don't use any of the structures defined by library functions, or you will get some fields garbled (because the library functions weren't compiled with that switch).

| Previous | Next | Up |

23. About this FAQ

Maintainer: Eli Zaretskii.

This FAQ is Copyright (C) 1994, 1995, 1996 by Eli Zaretskii. It may be freely redistributed with the DJGPP package or any part thereof, provided that you don't prevent anybody else from redistributing it on the same terms, and that this copyright notice is left intact.

Comments about, suggestions for, or corrections to this FAQ list are welcome. Please make sure to include in your mail the version number of the document to which your comments apply (you can find the version at the beginning of this FAQ list).

Much of the info in this FAQ list was taken from the DJGPP mailing list/newsgroup traffic, so many of you have (unbeknownst to you) contributed to this list. The following people read this list in its previous versions and provided useful feedback, comments, information and/or suggestions:


     Anthony Appleyard
     John Bodfish
     Bill Davidson
     DJ Delorie
     Juergen Erhard
     Gordon Hogenson
     Pieter Kunst
     Alexander Lehmann
     Steve Salter
     Charles Sandmann
     Terrel Shumway
     Stephen Turnbull
     Santiago Vila
     Morten Welinder
     Anthony Edward Wesley

| Previous | Next | Up |

24. Topic Index

This is an alphabetical list of all the topics covered in this FAQ. Use it to search for a description of your problem and follow the link to find the answer(s).

| Previous | Up |

25. Program Index

This index lists the problems and solutions by the program/package to which they pertain. If you know what program or package gives you the trouble, look it up here.