This is the DJGPP Frequently-Asked Questions List.
Copyright (C) 1994, 1995, 1996, 1997 Eli Zaretskii
This is the second edition of the FAQ list, and is consistent with version 2.01 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.
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.10 of the FAQ, last updated 19 January 1997, for DJGPP Version 2.01.
Another place to look for DJGPP documentation is the DJGPP Knowledge Base.
Brennan Underwood maintains a home page which is another valuable source for information about DJGPP.
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.
A previous version of this FAQ was translated into French, also available through the WWW.
The following master menu lists the major topics in this FAQ list, including all the indices.
Q: I have this problem which I absolutely MUST solve NOW! What do I do?
Use the DJGPP News group or mailing list. For most questions, you will have your answer in a day or two. See the details on how to ask the gurus.
This depends on your hardware and software. See system configuration guidelines.
Check out the list of required and optional packages.
See subscription instructions.
This FAQ includes the description of DJGPP archive search server, set up by DJ Delorie, which you should use whenever you have any questions or look for an information on a DJGPP-related subject.
DJ Delorie is the developer and principal maintainer of DJGPP, but anyone is welcome and encouraged to contribute.
| Previous | Next | Up | Top |
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?
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, Windows NT (on Intel CPUs), Novell NWDOS 7 and Caldera's OpenDOS (but several people have found the DPMI services of NWDOS and OpendDOS incompatible with DJGPP, so they should probably be turned off and CWSDPMI used instead), and Linux DOSEmu environment.
| Previous | Next | Up | Top |
Q: DJGPP Make crashes when I run it on OS/2!
If the above doesn't help, please post the details of the crashes you see to the DJGPP News group (see description of the DJGPP news group) or mailing list (see how to post to the mailing list), and somebody will help you.
| Previous | Next | Up | Top |
gcc.exe
anymore, as it is not needed.
The DPMI server built into NT (and Windows 95) loses selectors with each child program that is invoked by a DJGPP program, so after about two thousand calls to functions from the
spawnXX
family you can see an error message like this:
Load error: no DPMI selectorsThis problem is likely to afflict only DJGPP ports of Unix shells (such as bash), since no other DJGPP program, not even Make, is likely to call so many child programs before it exits. The only known work-around is to exit the shell every now and then, because when all the available selectors are exhausted, the DOS box will crash. I'm told that Make was seen crashing on long
Makefiles
on Windows 95, where the selectors are lost at even higher rate than on NT. If you ever run a very long Makefile
and see
Make crash, just run Make again, and it will pick up where the crashed session has left off. Note that the long filename API (the special LFN-aware functions of Int 21h) for DOS box is not supported by current versions of Win/NT, so you cannot have long filenames there from DJGPP programs.
You might have problems with using the SVGA modes of your video card under Win/NT. That is because NT doesn't allow direct access to the SVGA registers, without which it is impossible to recognize
the type of the SVGA and employ its capabilities. For example, a user reported that GRX functions and the MODETEST.EXE
program thought that only a standard VGA was installed, whereas he
had an S3 card. There is nothing you can do about this feature of Win/NT; that is the price you pay for the stability and protection you get under this OS (a runaway program that accesses hardware
registers can wipe out your disk or wedge the entire system cold). However, I'm told that Win/NT 4.0 supports DirectX which is a method of accessing screen, audio and other peripherals
directly, so it's possible to use full GRX graphics capabilities there.
Programs that use the "nearptr" facility of DJGPP to access absolute memory addresses (e.g., for memory-mapped devices) won't work on NT, because its DPMI server silently ignores functions that set
huge limits on selectors. Since the default algorithm which allocates memory from the DPMI server needs to set such huge limit in some rare cases, there's a small probability that a program will
fail or crash even if it doesn't set selector limits in user code. It is best to use the Unix-style sbrk
algorithm in programs that run on Windows/NT. See the library docs for
_crt0_startup_flags
where the _CRT0_FLAG_UNIX_SBRK
bit is explained, for more info on this issue. If you cannot switch to the Unixy sbrk
(e.g., if you
don't have access to its source), I'm told that sometimes such problems can be worked around if you run DJGPP programs in a full-screen session; your mileage may vary.
Some people report that NT servers cause much more problems than NT workstations of the same version and build. It seems that these problems usually mean that NT installation was done incorrectly (maybe it is much harder to get it right with a server than with a workstation?). If you have such problems, try to install a workstation, or re-install the server, and see if that helps. And if you gain some insight as to why servers like DJGPP less than workstations, please tell what you've learned.
The Cygnus Win32 project is another (unrelated to DJGPP) port of GCC and development tools to WinNT and Win95 platforms, which specifically targets development of Windows programs. It is available from the Cygnus archives or through the Web.
| Previous | Next | Up | Top |
Q: I can run DJGPP on Linux, but Make crashes with SIGFPE on even the simplest Makefiles!
You might also need to edit the RAM section of the dosemu.conf
file to make it comfortable for DJGPP. I suggest setting dpmi and xms to 16MB and
ems to 4MB.
Some users reported that Make, and possibly other programs which use floating point computations, crash in DOSEmu environment on systems without an FPU, even if you set the 387 and EMU387 environment variables correctly (as explained in Setting up the FP emulator, below). The only known work-around is to not use floating point or to upgrade your machine hardware. It is possible that newer versions of Linux might solve this problem too, so try upgrading your Linux software.
If your only problem is to run GNU Make, get the latest DJGPP port of Make, since ports of Make 3.75 or later can be configured to not issue FP instructions at all.
| Previous | Next | Up | Top |
| Previous | Next | Up | Top |
Another problem with RSXWDK is that the Makefiles there are written for ndmake, so they should be rewritten for GNU Make to work. Some more hacking of Makefiles might be required due to
the fact that they are set to work with EMX, and assume you unpacked everything into /rsxwdk.
You will also have to recompile the libraries as they were compiled with DJGPP v1.x, and
hack the v2 startup file crt0.s
along the same lines as the v1 version which comes with RSXWDK. (crt0.s
comes with the DJGPP source distribution, djlsr201.zip
.)
Apart from RSXWDK, you will need a windows.h
header file. One place to find it is with the WINE distribution (you'll have to add
-DWINELIB to CFLAGS when compiling). However, be warned that this is a complete rewrite of the original, and might produce error messages when used to compile Windows apps. I don't know about a
better solution except using windows.h
from a commercial compiler, which might get you into legal trouble.
You will also need a help compiler, or try at the Microsoft ftp site. I'm told that, legally, you must already have purchased a help compiler from Microsoft to use either one of these.
A resource compiler is also required. RSXNT (below) includes one such, but I didn't yet hear any success stories using it. Anybody?
Note that, according RSXWDK's author, that package is meant for those who already have working debugged Windows applications and are simply looking to port them to 32-bit code. Therefore, some crucial parts of a development environment (like a debugger) are missing there. The author of RSX has recently discontinued his support of the package and switched to RSXNT project that targets Win32 (Win9x and WinNT) platforms (below).
As of this writing, nobody has reported any first-hand experience of using RSXWDK with DJGPP v2; the above is based on user reports under v1.x. If you try RSXWDK with v2.x, please post a summary of your experience.
There is also a newer Windows development tool-chain by the author of RSXWDK called RSXNT. This is targeted for Win32 platforms (Win95 and WinNT); it does have debugging tools included and has
better support for DJGPP v2.x, but it needs to be registered (for a fee) if you want to develop commercial or shareware applications with it. It can be found on the same sites as RSXWDK and comes
with header files from Cygnus. You can find the DJGPP-specific version of RSXNT on SimTel mirrors. The sources of all
the RSXNT utilities can be found in rsxnt1.zip
archive on Cica mirrors, in the win95/programr/
directory. Note that currently, due to limitations of DJGPP, you cannot
produce DLLs or programs that will run on Win32s platforms with RSXNT.
Another way to develop Windows applications is to use the Cygnus GCC/GPP port. You can also download it via anonymous ftp. This one's compatible with Win32 (Win95 or WinNT, not Win32s), but requires you to comply with the GNU Copyleft system. The Cygnus distribution includes development environments which run on WinNT and Linux, targeting WinNT and Win95 platforms. Note that, as of this writing, the Cygnus port is still in early beta phase, and some nasty bugs are bound to be there. Contact Steve Chamberlain, for more details.
A better (but harder) way would be to volunteer to add Windows support to DJGPP.
| Previous | Next | Up | Top |
TMPDIR
environment variable points to it (e.g., set TMPDIR=e:, if E: is the RAM drive letter);
| Previous | Next | Up | Top |
TMPDIR
to your hard disk and make the disk cache larger, if you can.
SETVER.EXE
, HIMEM.SYS
etc.) from your CONFIG.SYS
and AUTOEXEC.BAT.
TMPDIR
environment variable to a directory on your hard disk. Put a sufficiently large BUFFERS=
statement into your CONFIG.SYS
(I recommend setting BUFFERS=40,8) to make DOS file operations faster.
csdpmi3b.zip
archive) and set the "Minimum application memory desired before 640K
paging" parameter to 512K or larger. Depending on how much memory you actually have, you might need to further fine-tune this parameter. This parameter defines the lowest amount of extended memory
CWSDPMI will use; if your system doesn't have that much free extended RAM, CWSDPMI will use conventional memory instead, where usually there should be around 600K of free RAM.
SETVER.EXE
, HIMEM.SYS
) from your CONFIG.SYS
and AUTOEXEC.BAT.
TMPDIR
environment variable to a directory on your hard disk.
TMPDIR
environment variable to a directory on your hard disk.
TMPDIR
environment variable to it. If your RAM disk is less than 4
MBytes, GCC might run out of space there for very large source files (e.g., cccp.c file from the GCC source distribution), but this shouldn't happen unless the size of the source file you
are compiling approaches 1 MByte.
A tutorial is available on how to set up and get started with DJGPP.
| Previous | Next | Up | Top |
Lately, there has been considerable confusion caused by the fact that the repository which was long known by the name SimTel is no longer called that; its new name is CCT. The name SimTel has moved (along with its originator and long-time manager, Keith Petersen) to another distribution network which uses almost the same ftp sites, but in different subdirectories. The name SimTel is copyrighted by this new distribution network, and so CCT will have to discontinue its use of that name. Experience shows that SimTel.NET (not CCT) is better managed and updates propagate there much faster, so I advise you to try using SimTel mirrors first, and fall back to CCT only if a SimTel site is unavailable to you. In particular, DJGPP version 2.01 and later wasn't even uploaded to CCT sites.
This section lists the SimTel.NET mirrors; see below, for the list of CCT sites.
Note: ftp.simtel.net is actually several ftp sites arranged in a rotating pattern of IP addresses to help balance the load and to avoid access problems due to network outages and simultaneous user limits.
| Previous | Next | Up | Top |
Coast
. Therefore, if you don't find the directories listed below, replace "SimTel" by "Coast" and try again.
SimTel/vendors/
directory on most CCT mirrors about a year ago. This is because CCT claims a compilation copyright on its collection, to prevent people
from copying the CD-ROMs which are distributed by CCT. 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 |
djgpp
subdirectory (the exact path to it might
be different on different mirrors, check out the DJGPP archive path, for your nearest mirror.). Then issue the binary command and download files you need (see
the list of required files) with the get or mget commands.
| Previous | Next | Up | Top |
Gopher users can access CCT files through a Gopher client.
For those of you who only have an e-mail connection to the Internet, CCT 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 CCT list server with this command in the message body:
get simtel-mailserver.info
| Previous | Next | Up | Top |
.zip
files I need to download?
Note: The version numbers of the packages below might not be up to date. For the latest versions, check out the DJGPP Mini-FAQ posted weekly to the comp.os.msdos.djgpp news group.
as
, the GNU assembler; ld
, the GNU linker; and their docs.
djdev
distribution includes two simpler debuggers, edebug
and fsdb.
The latter presents a user
interface similar to that of Turbo Debugger.)
COMMAND.COM
and its 4DOS/NDOS
replacements) and can be used to run Unix Makefiles if you install a Unix-style shell (e.g.,
bash) and auxiliary utilities. It also supports long filenames on Windows 9x and MSDOS pathnames with drive letters.
emacs.README
before you begin downloading the rest.
00_index.txt
; it contains a full list of the distribution files and a short description of every file.
| Previous | Next | Up | Top |
Execution-only environment..................300 KBytes Developing C programs.......................13 MBytes Developing C++ programs.....................17 MBytes Developing Objective-C programs.............15 MBytes Additional storage for RHIDE................2.5 MBytes Additional storage for DJGPP sources........10 MBytes Additional storage for GDB..................1.1 MBytes Additional storage for Emacs................30 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...4 MBytesNote that the above lists only approximate numbers. In particular, the disk cluster size can significantly change the actual disk space required by some of the distributions (those with a large number of files). The numbers above are for disks up to 512MB which have 8KB-long clusters.
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 much DPMI memory and swap space DJGPP applications can use. Depending on
your DPMI host, you might need to review its virtual memory settings in addition to leaving free disk space; CWSDPMI requires only that enough free disk space be available, but other
DPMI hosts have special settings to specify how much virtual memory they let their clients use, as explained below.
Q: Pulling that many megabytes through the net from my overloaded SimTel.NET mirror is almost impossible. Can't you prepare a ZIP archive which only includes stuff I can't do without?
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 with a shell account), can use a nice FTP-automating utility called AutoWinNet (get the file autownNN.zip from your nearest CCT mirror).
As for the minimal DJGPP installation, volunteers are welcome to prepare such an archive and make it publicly available, in the same spirit as EZ-GCC did for DJGPP v1.x.
| Previous | Next | Up | Top |
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:
Get the file txi390b.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.
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.) RHIDE also has an integrated Info reader, which is the core of its help system.
| Previous | Next | Up | Top |
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.txiThe Makeinfo program is part of the Texinfo distribution which is available in txi390b.zip.
If you prefer reading the docs through the Web, point your Web browser to the docs page of the DJGPP Web site.
| Previous | Next | Up | Top |
*.txi
or *.tex
) which you get with the source distribution of every package you download. You
will get a .dvi
file which you can print; or you can run a DVI-to-PostScript converter such as DVIPS to produce a PostScript output. DVIPS is a free program;
you can find it on SimTel.NET mirrors. 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 latest GNU or DJGPP
Texinfo distribution which includes that file.
If you'd like to produce printed docs of the library reference, TeX might complain that it cannot find a file named libc2.tex
. This file is generated from all the
*.txh
files in the DJGPP source distribution (djlsr201.zip
). In order to build this file, you need to install djlsr201.zip
, then go to the
src/libc
directory and type this from the DOS command prompt:
make -C ../mkdoc make docIf the above command fails due to unresolved externals, you will need to edit the file
makefile
in the mkdoc
directory. It has a line which calls ld
(the
linker), where you should change -lgcc -lc into -lgcc -lc -lgcc. Save makefile
and try the above commands again. Note that some documentation files (notably, those for GCC) will produce voluminous print-outs. You have been warned!
| Previous | Next | Up | Top |
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:
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 |
info/
subdirectory, but I can't find docs for some of the utilities, like Sed or Gprof.
*s.zip
) for that package and look inside it, usually in the directory called man
or doc.
| Previous | Next | Up | Top |
foo.1
files?
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?
*.1
troff source files.
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 DJGPP port of GNU Less, which uses colors to show bold and underlined letters. Alternatively, you can get the latest official GNU Less distribution which can be compiled out of the box with the Borland C compiler. (Future versions of Less will also compile with DJGPP.)
Another possibility for reading formatted man pages would be with an Emacs editor, if you use one. Emacs has a special command to read man pages, but it requires a port or a clone of a Unix man command, described above.
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.djgpp
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.
README
files (named README.dj
, README.dos
or some such), which explain
DOS-specific issues; you should read them before any serious use of the package, or in case of any problems. If this doesn't help, download the sources and look there, or ask on the net--either the
DJGPP News group or appropriate GNU News groups.
| Previous | Next | Up | Top |
v2misc/csdpmi3b.zip
from SimTel.NET mirrors) which is a free DPMI server written for DJGPP.
| Previous | Next | Up | Top |
Q: I cannot run v2 applications: they all hang or reboot my system, while v1.x apps run OK. Is this what v2 is all about--getting me out of the DJGPP community?
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.
Yet another cause of crashes in Info might be trailing whitespace in the DJGPP.ENV
file. The telltale signs of this failure are a stack dump that is bogus or doesn't start
with your `main' function, or a series of SIGSEGV that won't stop. Actually, this is a bug in the DJGPP v2.0 startup code, so any v2.0 program could crash in this way, but since the last section of
stock DJGPP.ENV
belongs to Info, it is the one which suffers most from this bug. Make sure your DJGPP.ENV
doesn't have a ^Z character at the end
(some DOS editors put it if you edit the file), and doesn't end with a blank line. Alternatively, upgrade to DJGPP v2.01 or later, where that bug is fixed.
| Previous | Next | Up | Top |
Q: The compiler prints "Virtual memory exhausted" and dies while compiling some long functions with some optimization options, such as -funroll-loops or -fforce-addr.
cc1.exe
or cc1plus.exe
need preposterously large amounts of
stack space, but only when you turn on optimizations. (One user reported that an innocent-looking C source file required 700KB of stack before cc1.exe
was able to compile it with
optimizations!) Try stubediting the compiler to enlarge its stack, as described elsewhere in this FAQ, how to enlarge the stack, before you try any other remedies in this
section. GCC 2.6.0 was known to crash when optimizing, especially when compiling C++ programs, but it can also happen for later versions, especially if your code has some syntactic or semantic bug. (This is usually a genuine GCC bug, not something special to DJGPP.) Upgrade to the latest version of GCC. If that doesn't help, 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.
If GCC reports that it has exhausted virtual memory, you should first see if your swap space is large enough (run go32-v2 with no arguments) and make more free space on your disk if so. Some users have reported that GCC seems to run out of virtual memory if TMPDIR environment variable points to a RAM disk which doesn't have enough free space. Changing TMPDIR to point to a hard disk would reportedly save the day in those cases.
An undocumented GCC switch can sometimes help you zero in on the code fragment that causes GCC to crash. If you add -Q to the GCC command line, it will print the name of every function it compiles. The function that makes it crash is probably the one whose name is the last one printed, or the one after that.
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 optimization which goes back as far
as version 2.5.8 and is only corrected in GCC 2.7.2.1 or later; this bug raises its ugly head on rare occasions, but is notoriously hard to hunt down when it does. (The stock v2.0 distribution
should by default disable this kind of optimizations on the lib/specs
file, and v2.01 comes with GCC 2.7.2.1 where that bug is fixed.)
As an extreme measure, don't optimize at all, if that's the only way to make your program compile.
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.
Yet another cause for such crashes can be connected with excess memory usage that GCC needs when compiling certain programs, which makes some DPMI hosts fail. For details about this, see CWSDPMI allocation problems, in the next section.
| Previous | Next | Up | Top |
Q: When I try compiling a program, GCC aborts saying "Installation problem, cannot exec `as': No such file". What does that mean?
Q: GCC aborts with "Internal compiler error" when compiling a large C++ program.
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.
A typical case is when people fail to install the
Binutils package and GCC cannot find as.exe
(the assembler) and ld.exe
(the linker). You can use
the -v switch to GCC to see what programs it invokes and which one of them causes the fatal error. 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, and the DPMI server fails to allocate it because it exhausts available memory for its internal tables. Release 1 of CWSDPMI can fail like this if an application asks for a large number of small memory chunks. If you use release 1 of CWSDPMI, you can enlarge the maximum space that CWSDPMI uses if you get a CWSDPMI heap-fix patch. Beginning with release 2, CWSDPMI defines a larger (6KB) default heap that is configurable by CWSPARAM program to be anywhere between 3K and 40K bytes, without recompiling CWSDPMI. You should upgrade to the latest CWSDPMI if you experience such problems.
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). If you see such problems when compiling a C program, stubedit cc1.exe.
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;Note that the Unix algorithm for
sbrk
might cause trouble in programs that install hardware interrupts handlers.
| Previous | Next | Up | Top |
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!!!
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 short, most viruses cannot attach themselves to it without overwriting the beginning of the DJGPP COFF image which specifies vital
information such as location and length of various program sections, 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 a v2.0 gcc.exe
driver with cc1plus.exe
, cc1.exe
or other programs from an old v1.x
distribution.
| Previous | Next | Up | Top |
"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 |
make.exe
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. That's because v1.x programs cannot spawn v2 programs directly (the v1.x program sees that the child is a DJGPP program and tries to call go32 to run it, but v1's go32 cannot run v2 programs). The result usually will be that the child either crashes or silently exits. 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.) You can use go32-v2 to work around this limitation (see description of go32-v2, below), but I suggest doing that only if you absolutely cannot upgrade to v2's Make.
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 (that is usual for Makefiles that come from Unix). To work around, truncate the filename of that program in the Makefile.
| Previous | Next | Up | Top |
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 old 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 with 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 the bin/
subdirectory of your main DJGPP directory.
| Previous | Next | Up | Top |
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.
Another cause of such problems might be that your system is set up inefficiently. If GCC gets too few free RAM, it will run very slowly, and you might think it crashed when in fact it didn't. (This kind of problem usually happens on memory-starved machines.) Check out the system configuration advice, in this FAQ list and configure your system accordingly.
| Previous | Next | Up | Top |
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 are hidden by the graphics display. How can I see it?
stderr
, and stock COMMAND.COM
cannot redirect it. There are several alternatives to do that:
COMMAND.COM
, such as 4DOS or bash, which knows how to redirect standard error stream to a file. 4DOS is shareware and can
be found on CCT mirrors, while bash is available
from the DJGPP archives.
redir -o gcc.log -eo gcc -v ...(put the rest of the GCC command line instead of the dots). The messages printed by GCC will be written to the file
gcc.log
.
| Previous | Next | Up | Top |
Q: I don't have time to download all these messages, not to mention looking through them. Can't you DJGPP gurus help me? Please??
bin/
subdirectory) and save its output.
ENVIRON.LST
, the output of go32-v2, the contents of your AUTOEXEC.BAT
and CONFIG.SYS
, and
what GCC printed during compilation with the -v switch (if your problem is that GCC won't work).
symify
on the stack dump, and post the output of
symify
:
symify -o dumpfile yourprog(See detailed description of symify, for more details about
symify.
)
| Previous | Next | Up | Top |
| 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 accordingly. 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 percent 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 CWSDPR0 as your DPMI host, or use the CWSPARAM program to point the swap file to a non-existent drive), or use PMODE/DJ as the DPMI host, then run the compilation again; if the compiler aborts with an error message saying there isn't enough memory, then it was paging in your original environment.
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 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 the 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. Some people disable the delayed-write feature for safety reasons, to avoid losing files due to system crashes. If you are worried about this, you can usually gain performance without sacrificing safety by enabling delayed-write together with an option that causes the cache to flush the write-behind data before the system returns to the DOS prompt. (For SmartDrv disk cache, this is achieved by specifying /N/F switches instead of /X.) GCC usually gains a lot when you set up your cache in such a way, because each compiler pass (pre-processor, compiler, assembler) must write temporary files that are used by the following passes.
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 versions of the library.
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 valuesIncorrect 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 166 MHz Pentium system with 32 MBytes of RAM and 4 MBytes of RAM disk compiles the entire GCC source in under 10 minutes (this takes about 45 minutes on a 40MHz Sparc2).
A few users have reported that they got much faster linking after they've stub-edited ld.exe
to change the transfer buffer size to 64KB. This speedup effect is usually seen when DJGPP
is installed on a networked drive, or on a compressed disk; when DJGPP is installed on a local disk drive, linking speed is not affected by the size of transfer buffer.
If you use a disk cache, make sure you enable its write-back (aka delayed-write) operation. Some people disable the delayed-write feature for safety reasons, to avoid losing files due to system crashes. If you are worried about this, you can usually gain performance without sacrificing safety by enabling delayed-write together with an option that causes the cache to flush the write-behind data before the system returns to the DOS prompt. For SmartDrv disk cache, this is achieved by specifying /N/F switches instead of /X.
For very large (several MBytes) executables which are built from a large number of small source files, the link (as opposed to the compilation) 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. Make sure that the linker wasn't stub-edited to make its transfer buffer too small.
Another reason for slow linking might be that the DJGPP.ENV
file by default sets TMPDIR
to a tmp/
subdirectory of the main DJGPP installation directory; if
DJGPP is installed on a networked drive, this means all your temporary files go back and forth through the network (and networked disks are usually not cached on your PC). In such cases, setting
TMPDIR
to a directory on your local drive, or to a RAM disk, would probably make linking faster.
This chapter explains how to solve some of those problems which tend to appear when compiling and linking your programs.
| Previous | Next | Up | Top |
Q: When I link my programs, ld.exe complains that it cannot open crt0.o, although that file exists in the lib subdirectory...
set DJGPP=c:/djgpp/djgpp.envand it should point to the correct path of the file
DJGPP.ENV
on your system (the file itself comes with the file
djdev201.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.
Sometimes, people make errors in their AUTOEXEC.BAT
that cause the DJGPP variable to be defined incorrectly, or not defined at all (some of the more common errors are listed
below). To check what is the actual setting, type from the DOS prompt:
set > env.lstthen examine the contents of the file
env.lst
. You should see there a line like this:
DJGPP=c:/djgpp/djgpp.envIf a line such as this isn't there, you should investigate the cause for this (see below for some of the possibilities).
Many problems with setting DJGPP happen when people put excess blanks around the = character, which has the effect of defining "DJGPP " (with the blank) which is not the same as "DJGPP" (without blanks). You should make sure there are no such excess blanks, or DJGPP won't find its files.
Another possible cause of DJGPP variable not being set is that you invoke another batch file from your AUTOEXEC.BAT
before the line that sets DJGPP. Make sure such
batch files are invoked with the CALL
statement, because otherwise the subsidiary batch file will never return to process the rest of AUTOEXEC.BAT
(that's a "feature" of
DOS batch file processing).
The code that processes DJGPP.ENV
assumes that this file resides in the main DJGPP installation directory. If that assumption is wrong, the compiler (and some other DJGPP programs)
might fail to find some of the files or auxiliary programs they need. Do NOT move DJGPP.ENV to any other directory!
Note that if you run DJGPP under Win95, WinNT or any other environment that supports long filenames (e.g., if DJGPP is installed on a networked drive whose network redirector supports long
filenames), you cannot use long names of the directories in the pathname of DJGPP.ENV
when you set the above variable in the environment; you should use their 8+3
aliases instead. First, some of these systems (such as WinNT) do not even support the LFN API for DOS programs. But even if LFN API is supported, e.g. on Win95, DJGPP won't know that it
should support LFN until after it read DJGPP.ENV
--it's a chicken-and-egg problem. For example, the following setting won't work because
Development
is longer than 8 characters:
set DJGPP=c:/Programs/Development/Djgpp/djgpp.envIf the DJGPP variable is set correctly, then check the following possible causes of this misbehavior:
DJGPP.ENV
in a way that invalidated some of the settings there; try restoring the original file from the distribution to see if that fixes your problems.
Be sure you are familiar with the syntax of DJGPP.ENV
before you edit it. The DJGPP server has a page with a
description of the DJGPP.ENV
syntax.
The syntax of DJGPP.ENV
is also described in the DJGPP Knowledge Base, which comes with the djdev distribution.
crt0.o
reside on a networked drive. This is due to a peculiarity of Novell that
happens to fail the library function stat
in some cases. The exact reason of the failure has been identified, and the library which comes with DJGPP v2.01 includes a version of
stat that works around that problem, so the linker from v2.01 is free of this bug, and upgrading will solve this. Another solution would be to upgrade your Novell software; version 4.x
is reportedly free of this problem, even if you use DJGPP v2.0.
gcc.exe
driver to some other name. In this case, you should edit the file DJGPP.ENV
to add a section named after the new name of GCC, which is an exact
duplicate of the section called [gcc]. DJGPP start-up code uses this file to find environment variables which it should put into the environment before the main
function
is called, but it searches for the relevant variables using the actual name of the program, so when you rename the executable, it can't find its section and doesn't put the necessary variables into
the environment.
CONFIG.SYS
is insufficient, so GCC runs out of available handles.
You should have at least FILE=15 in your CONFIG.SYS.
Presumably, there should be a parameter in some configuration file or a command-line argument to one of the network drivers which sets the number of files that can be open simultaneously on a networked drive; you should set it to be at least 15.
crt0.o
and if you follow -B with a directory other than that where
crt0.o
resides, the linker won't find it.
You should not need to use the -B or -L switches at all if your installation is correct and the DJGPP
variable points to the main installation directory,
because GCC should be able to figure out all the linker switches itself. If linking fails without explicit -L or -B, check out above for the possible causes.
| Previous | Next | Up | Top |
iostream.h
, _string.h
and other C++ headers. Where can I find those header files?
Q: GCC complains about 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??
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.
Another possible cause for problems with C++ include files is that your source file has a .c
extension. GCC then thinks that this is a C program and doesn't instruct the preprocessor to
search the include directories specific to C++. Rename your file to .cc
or .cpp
extension, or call GCC with the -x c++ switch, and the header files will be
found. A full list of extension rules which GCC uses to determine the source language can be found in the list of language-specific suffixes, elsewhere in this FAQ.
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 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:
HKEY_LOCAL_MACHINE
branch of the registry until you see in the left pane an item called HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem
,
then click on it.
FileSystem
key. If you don't see an item there called NameNumericTail
, select "New", "Binary Value"
from the "Edit" menu, then type NameNumericTail and it will appear. Now double-click on NameNumericTail
and enter a value of 0.
NameNumericTail
set to 0 breaks some programs, you can restore its original setting after you've renamed the files as described above. NameNumericTail
only
affects the short names of new files being created, it has no effect on the files that already exist.
| Previous | Next | Up | Top |
#include <stdio.h> int main () { printf ("%d \n" 10 //* / 2 //*/ 1 ); return 0; }(While admittedly perverse, this little monstrosity was written with the sole purpose of demonstrating 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.cAlternatively, 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.cSed can be found in the DJGPP distribution.
| Previous | Next | Up | Top |
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.
In the examples above, PROG.C
is taken as a 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
the -v switch to the GCC command line; if you see that 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 the -x LANGUAGE switch. For instance, the command
gcc -x c++ prog.ccompiles
prog.c
as C++ source. See the "Overall Options" section of the "The GNU C Compiler Manual", for more info on
-x options.
| Previous | Next | Up | Top |
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.
.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 |
#ifdef
directive to make it only visible under DJGPP?
__DJGPP__
, like this:
#ifdef __DJGPP__ ... DJGPP-specific code ... #else ... not seen under DJGPP ... #endif
__DJGPP__
has the 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 ... #endif #else .... get here in DJGPP v1.x or non-DJGPP environment #endifAnother 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 |
libgcc.a
and libc.a.
Some functions aren't included there, so the linker can't
find them. If you need to link against some optional library, say libxy.a
, put the library into the DJGPP lib/
subdirectory and append a -lxy to the link
command line. To use C++ classes in the libgpp.a
(it's called libg++.a
on Unix systems), append -lgpp. The Standard C++ Template classes are in
libstdcx.a
(it's called libstdc++.a
on Unix); append -lstdcxx. When linking C++ programs, you can use the gxx command instead of gcc; it will then instruct the linker to also scan the C++ libraries automatically, so you don't have to remember doing that yourself.
Note that the first release of DJGPP v2.0 didn't include gxx.exe
and the C++ STL library libstdcx.a.
If you cannot find them on your machine, download the latest
gcc272b.zip
and lgp271b.zip
archives that are dated 22-Feb-96 or later, or upgrade to DJGPP v2.01.
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 |
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 |
-lgpp -lstdcxx -lmE.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 -lstdcxxor, if you compile and link in one command:
gcc -o main.exe main.cc sub.cc -lgpp -lstdcxx -lmIf 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 -lstdcxx -lmWhen 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 directly, use the -L option to tell it where to look for the libraries.
| Previous | Next | Up | Top |
complex.h
and iostream.h.
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 |
Q: I looked into libgpp.a and there aren't any references to any Complex class functions. I also didn't find complex.cc source file in the source of Libg++ library. Where did the Complex class go?
class Complex
there is
now a template class complex
, and Complex
is now a typedef which uses that template class. Look into the headers lang/cxx/_complex.h
and
lang/cxx/std/complext.h
and you will see that change. Part of the code found previously on complex.cc
in the Libg++ source distribution is now found on
cdinst.cc
source file in the STL sources (look inside libstdcx.a
), another part is scattered between the various files included at compile time (such as
lang/cxx/std/dcomplex.h
and lang/cxx/std/complext.cc
), while the rest is generated by the compiler itself. Therefore, there aren't any predefined functions of class Complex
in libgpp.a.
Programs that use class Complex need to be edited to replace every instance of class Complex
to either just Complex
or
class complex.
As long as the C++ Standard is not officially published, C++ is still a moving target, and Libg++ releases that try to track it sometimes have no other alternative but to break existing code. If you use C++, you have to accept this as a fact of life.
| Previous | Next | Up | Top |
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.oThat's all!
| Previous | Next | Up | Top |
nm
, and I cannot find these creatures. Where in the world are they??
djgpp.djl
linker script that should be in your lib/
subdirectory. When you call gcc to link a program, it
invokes ld.exe
with the option -Tdjgpp.djl. If you invoke ld directly (this is generally not recommended), be sure to include that switch. If you did invoke it
through gcc, maybe your linker is set up incorrectly. Add -v to the GCC switches and check that the command line that GCC gives to LD includes that switch, that your
lib/
subdirectory includes that script file, and that the script file is intact and includes the definition of the above symbols.
Another reason might be that you have edited your DJGPP.ENV
file in a way that prevents the linker from finding its djgpp.djl
script.
Mixing an old v1.x installation with a v2.x one can also cause such problems. Be sure to delete the entire v1.x tree, or rename it, before installing the v2.x distribution.
| Previous | Next | Up | Top |
.exe
file
static
array has the 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?
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 | Top |
.exe
files so large?
Q: How come I recompile my programs with v2, and my executables become larger by some 20-30 KBytes? Isn't the latest version supposed to be better?
In general, v2 programs are about 20-30K larger on disk, but use 50-120K less memory at run-time, than v1.x programs. The larger disk image is due to two main factors:
Apart from getting to protected-mode, the DJGPP startup code also includes such functionality as wildcard expansion, long command-line support, and loading the environment from a disk file; these usually aren't available with other DOS protected-mode compilers. Exception and signal handling (not available at all in v1.x), FPU detection and emulator loading (which were part of go32 in v1.x), are now also part of the startup code.
If your program doesn't need parts of the startup code, it can be made smaller by defining certain functions with empty bodies. These functions are __crt0_glob_function
,
__crt0_load_environment_file
, and __crt0_setup_arguments.
By defining empty substitutes for all three of these, you can make the "Hello" program be 18KB on disk. These
functions are documented in the DJGPP libc reference, which see.
You can make your program image still smaller by compressing it with DJP
which is a DJGPP-specific
executable compressor. It is fast and has no memory overhead. It also supports DJGPP
Dynamically Loaded Module (DLM) technology.
Another cause for differences in executable sizes between v1.x and v2 might be the code generated by GCC: DJGPP v2 uses a newer version of GCC. Usually, the code size is quite similar, but in some cases GCC 2.7.2 has been seen to produce code which is 50% larger or 50% smaller than GCC 2.6.3 included with v1.12.
| Previous | Next | Up | Top |
djgpp.lnk
djgpp.lnk
file... Q: When I try to link a program, I get an error message which says that linker script file djgpp.lnk cannot be open. What gives?
djgpp
, Windows will create a
file djgpp.lnk
in your working directory. In that case, when ld.exe
looks for its linking script, it will find this shortcut instead, and will be totally confused by its
format and contents. In DJGPP v2.01 and later, the linker script is called djgpp.djl
, so that this conflict doesn't exist after you upgrade.
Another possible cause of such problems is RSXNTDJ. When you install it, it replaces some of the files which come with DJGPP by its customized versions, but since version 1 of RSXNTDJ is consistent
with DJGPP v2.0, these customized files still specify djgpp.lnk
as the linker script, whereas DJGPP v2.01 and later has renamed that file to djgpp.djl
. Please look into
your rsxntdj/lib/specs
file and see if it has a line like so:
%{L*} %D %{T*} %o -Tdjgpp.lnk\If so, you should change -Tdjgpp.lnk into -Tdjgpp.djl, and see if that solves the problem, or look for a version of RSXNTDJ which is compatible with your release of DJGPP. You should also compare the rest of the RSXNTDJ
specs
file with the one which comes with DJGPP and check for other inconsistencies.
| Previous | Next | Up | Top |
Q: I run STUBIFY on a networked drive under Novell, but it doesn't produce a .EXE file. How come?
SMODE stubify.exe 2 SMODE ld.exe 2
| Previous | Next | Up | Top |
Q: I have some large libraries that I cannot link because the linker fails on them with a message saying "memory exhausted". I have plenty of virtual memory on my system, so why would ld fail?
ld.exe
from GNU Binutils 2.5.2. Please upgrade to DJGPP v2.01 which comes with Binutils 2.7. If you can't upgrade, or if the latest
ld.exe
exhibits such bugs, these are your alternatives for a work-around:
calloc.
ld.exe
from GNU Binutils 2.7 (which comes with DJGPP v2.01) doesn't have most of these problems, but there are still some cases where you might see such messages. One such case is the
POVRAY package, where the failure is caused by an object file called _pmlite.o
in the library. The problem here is that _pmlite.o
is a TASM-compiled file,
processed by EMXAOUT. EMXAOUT produces a.out object files which ld.exe
cannot link if they are in a library. Either taking that object file out
of the library, or processing the original _pmlite.obj
with another tool (such as OBJ2COFF) will solve these problems. Note however, that the authors of
OBJ2COFF have explicitly forbidden commercial use of their tool.
Q: It seems I miss one of the source files from the Allegro distribution, because Make cannot find it when I try to build Allegro.
| Previous | Next | Up | Top |
Q: My v2 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?
malloc
is always zeroed, but v2 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
( -559838801
in decimal) 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 only under CWSDPMI; its telltale sign is a message "Page fault at ..." that is printed when a program crashes, and an error code of 6.
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 can be disabled by setting the _CRT0_FLAG_NULLOK
bit in _crt0_startup_flags
; if this makes SIGSEGV crashes go away,
your program is using such illegal pointers; the stack trace printed when the program crashes should be a starting point to debug this.
An insufficient stack size can also be a cause of your program's demise, see setting the stack size, below.
| Previous | Next | Up | Top |
bin/
subdirectory). To this end, make sure that your program was compiled
with the -g switch, linked without the -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-nameYou 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 yourprogYou 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 yourprogThis 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 the REDIR 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 |
Q: My program crashes when I read data files, but the same program on Unix works OK.
Q: When I read a file I get only a small portion of it.
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. Note that the above distinction between binary and text files is written into the ANSI/ISO C standard, so programs that rely on the Unix behavior whereby there's no such distinction, are strictly speaking not portable.
You can also use the low-level _read
and _write
library functions which give you the direct interface to the DOS file I/O; they always use binary I/O.
| Previous | Next | Up | Top |
Q: Help! I cannot make `gotoxy' work! The text I print appears on the screen in incorrect locations after I use `gotoxy'!
Q: Why does the text appear in the default colors even though I call `textcolor' and `textbackground'?
fprintf
, fputs
and the like) functions, or send your output to the C++ cout
stream? Then
what you see is the effect of the buffering of the standard output streams. The buffer is not written to screen until it's full, or until a Newline is output, which might produce very unpleasant and
unexpected behavior when used in interactive programs.
It is usually a 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 generally work under DOS and DJGPP, note that in some cases the operating system might further buffer your output, so sometimes a call like sync
would be needed to actually cause
the output be delivered to the screen.
The functions that set text attributes only affect the screen-oriented output (aka conio) functions ( cputs
, cprintf
etc.), the text written by
fprintf
and other stdio functions doesn't change. This is unlike some 16-bit DOS compilers where stdio
functions can also print colored text.
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 Sandmann, requests a notification by mail or acknowledged e-mail in case you distribute CWSDPMI with a commercial or shareware product. If your program could be run on a machine which lacks a 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, write to Charles Sandmann and ask him about a modified stub code that creates an image of CWSDPMI if none is found first time the program is run.
You can bind PMODE/DJ with your program, but remember that PMODE/DJ doesn't support virtual memory, so such programs will only run on machines with enough free physical RAM.
A tutorial is available on graphics programming with DJGPP.
| Previous | Next | Up | Top |
Q: How do I tell GRX which driver to use with my SVGA?
GRX20DRV
environment variable, like this:
set GRX20DRV=et4000 gw 1024 gh 768 nc 256To set that variable, you need to know the chip-set on your adapter; refer to your SVGA documentation. Currently, GRX supports the following chip-sets:
GRX20DRV
variable, run modetest.exe
to see what modes you have available. If your chip-set is not one of the above, try the VESA driver because many adapters support the VESA BIOS extensions. If yours doesn't, try installing a VESA BIOS emulator, like UNIVBE.
| Previous | Next | Up | Top |
0xa0000
, but get "Segmentation violation" ... Q: How can I access the text-mode video memory of my VGA?
_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 the _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 faster access (and don't want to write it in assembly), See using the "nearptr" access facilities, as described below.
If your video card supports the VBE 2.0 standard, you can access the linear frame buffer as a normal array in memory. For an example of such a technique, see the VBE example code by Charles Sandmann. You can also reach this file via the Web.
The only reasonable thing to do is to dedicate a "hotkey" in your application (e.g., Alt-R) whose action is to redraw the entire screen. If you do that, it's best to start all the way
from the beginning, with a call to GrSetMode
, as there are a few bad Windows video drivers which do not restore SVGA graphics modes properly upon the switch back.
| Previous | Next | Up | Top |
Q: What shall I install on a target machine which lacks hardware floating-point support?
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.dxeThis is probably due to some subtle bug in the emulator setup code. This code is hard to debug, because the people who developed it have machines with hardware FP processors. Volunteers with FPU-less machines are needed to help debug the above problem. If you have access to a system without an FPU and are willing to fix this problem, write to Charles Sandmann and ask him for guidance.
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. (But you will need to get the sources and recompile it, since it
was compiled with a beta release of DJGPP and will cause unresolved externals if you try linking against libwmemu.a
without recompiling it.) Note, however, that even WMEMU
doesn't solve all the problems of debugging FP programs on a non-FPU machine (e.g., emulating flags doesn't work).
| Previous | Next | Up | Top |
AUTOEXEC.BAT
, but DJGPP-compiled floating point programs still doesn't work. Why?
| Previous | Next | Up | Top |
| Previous | Next | Up | Top |
| Previous | Next | Up | Top |
_control87
can be used from within a program to set the coprocessor to a non-default state.
| Previous | Next | Up | Top |
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 | Top |
gcc2721s.zip
, install the above patch, rebuild cc1obj.exe
, and then recompile libobjc.a
to make the problem go
away.
ldexp
function, my program crashes with SIGFPE. What's wrong?
libm.a
library released with DJGPP v2.0 which affects several library functions such as ldexp
. A work-around is
to link without -lm switch; this will cause GCC to use math functions from libc.a
. If you need math functions which are only in libm.a
, or if you
need libm.a
for better numerical performance, a patched version of libm is available, courtesy of
Tom Demmer. DJGPP v2.01 corrects this bug, so upgrade to that version if you can.
| Previous | Next | Up | Top |
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.exeBeginning with v2.01, DJGPP debuggers can debug both unstubbed COFF images and DOS-style .exe executables (v2.0 only supported COFF files). To debug a COFF file, name it without the .exe extension, like so:
gdb myprogYou can use one of several available debuggers with DJGPP:
stdin
or stdout
, you will be unable to communicate
with GDB.
gdb.ini
instead of .gdbinit
which isn't a legal filename under MS-DOS.
~/.inputrc
on Unix) is called /inputrc
on MS-DOS and
should be in the root directory of the current drive.
<debugger-name> <program> <args...>Note that the
argv[0]
parameter under the debugger is not the full pathname of the debuggee, so programs which use argv[0]
for their operation might behave
differently under a debugger.
| Previous | Next | Up | Top |
qdpmi off
| Previous | Next | Up | Top |
.exe
program. That version of 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 look this way:
gcc -o foo foo.oinstead 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.exeDebuggers which come with DJGPP v2.01 can debug COFF and .exe programs alike, so upgrading to v2.01 should solve this problem.
| Previous | Next | Up | Top |
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 |
gdb myprog > prnThis will only work if the program itself doesn't write to stdout (graphics programs usually don't); 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 a low-level debugger. Press Alt-F5 to switch between the two screens. Stock FSDB as distributed with DJGPP can only do this with text screens, but a modified version of FSDB with graphics support is available that knows about many graphics modes (it can also be found on the Oulu repository).
Future versions of RHIDE might allow debugging graphics programs, so try to find out whether such a version is available.
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. Be sure that you don't have some other TSR installed that catches screen writes and bypasses the BIOS functions, or else MSHELL won't help you. For example, changing the code page (with the DOS CHCP or MODE commands) might do this.
| Previous | Next | Up | Top |
.cc
source
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?
.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 | Next | Up | Top |
CMPForward
has a
method named go
which you need to put a breakpoint in, use the following command:
b 'CMPForward::go'Other GDB features that might be useful in this context are the various demangling options, like set print demangle, set demangle-style etc.; look them up in the GDB on-line docs.
However, there are some cases where you won't be able to get GDB to demangle C++ function names no matter how hard you try. This is due to a lack of sufficient debugging information in the COFF
files with SDB debug data. There's simply not enough info there for GDB to detect the source language and use C++-specific support. If you need a description of the GNU style of mangling C++ names
(so you could demangle them yourself), look in the GDB or Libg++ source distribution, in the libiberty directory, for a file named cplus-demangle.c
. If you really need full C++ support
in DJGPP, you will have to recompile GCC with stabs debugging support. Robert Hoehne, who did that, reports that it is only necessary to
change the configuration file go32.h
in the GCC sources and rebuild cc1.exe
and cc1plus.exe
. Caveat emptor: FSDB and EDEBUG32 don't
understand stabs, so you will have to compile with -gcoff option to use these debuggers.
Note that, as the debugger built into RHIDE uses GDB code, it will also sometimes have such problems with debugging C++ programs.
| Previous | Next | Up | Top |
Q: I cannot debug code produced by Flex, or Bison, or F2C, because GDB somehow messes up all the source file and line number info!
#line
directives from the generated C source, and debug the generated code as regular C program.
Q: I cannot debug any program which catches signals!!??
Q: I compiled my program with -pg switch, and now I cannot debug it...
Q: When my program hits a breakpoint in GDB, the debugger reports SIGSEGV, but only under Windows...
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 FP hardware (unless you use WMEMU as your emulator, but even WMEMU doesn't solve all the
problems). The reason for all these problems is that any exceptions or signals that happen when your program runs under a debugger will be caught by the debugger instead, and they won't get passed
to the debuggee. To debug programs which hook hardware interrupts, you will have to chain the old real-mode interrupt handler to your new handler, which requires to write special debug version of
the program. 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 where 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). Some programs (but not Emacs) will also treat the Ctrl-2 keypress as Ctrl-C.
Another known problem is that GDB GP Faults when the program hits a breakpoint under Windows 3.x (Windows 9x doesn't have this problem). This is because the breakpoint instruction causes a software interrupt (as opposed to an exception) under Windows 3.x, and the DJGPP debug support currently only catches debug exceptions. The only work-around is to use the hardware breakpoints (which use the special debug registers of the i386 and higher CPUs, and which do work with DJGPP on Windows 3), and never have more than 4 of them active at the same time. FSDB will automatically use the hardware breakpoints for the first 4 breakpoints (so it works on Windows 3.x unless you set more than 4 breakpoints simultaneously), but with GDB, you will have to explicitly use the hbreak and thbreak (instead of break and hbreak) commands which set hardware breakpoints. This works with DJGPP ports of GDB 4.16 and later. Note that GDB uses the ordinary breakpoints to implement the step, next and similar commands, so you can't use these on Windows 3.x; use the temporary hardware breakpoints instead. The above is also true for watchpoints (which watch for variables to change value): you need to use hardware watchpoints with GDB (the total number of breakpoints and watchpoints cannot exceed 4). Same considerations apply to the debugger built into RHIDE.
| Previous | Next | Up | Top |
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 |
| Previous | Next | Up | Top |
Q: I run Gprof on my program, and it says: "bad format".
.exe
file instead, it
will be most unhappy. The way to produce the COFF output is explained in the section dealing with GDB, above. Alternatively, upgrade to DJGPP v2.01, where all Binutils
programs know about .exe executables.
| Previous | Next | Up | Top |
Q: I can't figure out some of the info in the Gprof report ...
gprof.1.
If you don't have one, you will have to look for it in the
Binutils distribution.
| Previous | Next | Up | Top |
__dpmi_int
so heavily used?
__dpmi_int.
Can't you guys make
your library right?
__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.
gmon.out
and why won't gprof
compute the profile?
gmon.out
is the file with raw execution counts and timing info that gprof needs to produce the profile. The file is written by the profiled program
when it exits. If the file isn't created, it might be because one of the following reasons:
gmon.out
are only linked in when gcc sees -pg on the link command line.
ld.exe
directly to link your program and forgot to mention the files and switches necessary for the profiled program operation. You should use gcc to
link your program instead of calling the linker directly; a -pg switch to gcc is all that it takes to make sure that the linker will get all the necessary arguments.
Note: If you absolutely need to call ld.exe
directly, invoke gcc once with a -v switch and you will see what the arguments are that you should
pass to the linker in your case.
gmon.out
is registered with the atexit
library function, and won't be called if the program was
terminated in an abnormal way. Make sure that your program exits with a call to exit
library function or with a return
statement in your main
function.
For example, if your program dies with an exception or a signal, install a signal handler and make it call exit.
| Previous | Next | Up | Top |
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?
| Previous | Next | Up | Top |
Q: I timed a test program and it seems that DJGPP v2.01 produces slower executables than v2.0, which in turn was slower than v1.x. Why are we giving up so much speed as we get newer versions?
Comparison between GCC 2.7.2 (in v2.0) and 2.7.2.1 (in v2.01) shows that 2.7.2.1 optimizes just as well as 2.7.2, but it takes a different combination of the optimization-related options to achieve the greatest speed in each compiler version. The default optimization options has also changed; for example, -force-mem is switched on by -O2 in 2.7.2.1; it wasn't before. GCC offers a plethora of optimization options which might make your code faster or slower (see the GCC docs for a complete list); the best way to find the correct combination for a given program is to profile and experiment. Elliott Oti suggests the following tips:
| Previous | Next | Up | Top |
Q: I run the same program on a 486 and on a Pentium, and it's slower on a Pentium!!
A program might sometimes run slower on a Pentium due to alignment problems in DJGPP. GCC makes assumptions about how GAS (the assembler) handles alignment, but when GAS is built with the default DJGPP configuration, it treats alignment in a way that's different from what GCC assumes. The outcome of this is that longs are word-aligned, doubles are dword-aligned, etc. Depending on the DJGPP version, link order, library differences, you might get lucky (or unlucky) with a 50/50 chance to get an improper alignment. Different CPUs have different penalties for unaligned accesses, which may explain differences in speed.
You might consider adding some slack static variables to induce changes in alignment; if any of the changes suddenly cause a significant change in the runtime performance, then alignment might be the reason.
| Previous | Next | Up | Top |
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?
Some programs which only copy data between two files might gain significantly if you write your custom low-level I/O functions that avoid moving data to extended memory (only to move them back to the transfer buffer). However, these cases are rare.
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.
__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).
| Previous | Next | Up | Top |
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 in
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). Under Windows 9x, the memory settings
of the DOS Applications' Property Sheet define how much virtual memory a DJGPP program will get (see Win9x allocation details, below).
| Previous | Next | Up | Top |
malloc
/ free
don't affect virtual memory...
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.
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 |
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
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 |
NULL
pointer from malloc/calloc
! Q: Why is my program dying with SIGSEGV under CWSDPMI when allocating a chunk of memory?
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)
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.
If your program asks for memory in lots of small allocations, then it might crash when you use CWSDPMI as your DPMI host. This is because CWSDPMI runs out of its tables where it tracks memory allocations. If you use release 1 of CWSDPMI, you can enlarge the maximum space that CWSDPMI uses if you get a CWSDPMI heap-fix patch. Beginning with release 2, CWSDPMI defines a larger (6KB) default heap that is configurable by CWSPARAM program to be anywhere between 3K and 40K bytes, without recompiling CWSDPMI. You should upgrade to the latest CWSDPMI if you experience such problems.
| Previous | Next | Up | Top |
PageOverCommit=nin 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 |
Note that you cannot allocate more than half the available memory in one chunk under Windows 9x, exactly as the things are under Win3.x, and you cannot have more than 64 MBytes of virtual memory available to DJGPP programs running on Windows.
| Previous | Next | Up | Top |
Q: I have 5 MBytes of free RAM on my machine, but DJGPP programs start paging after only 256KBytes of memory were used??
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 it should 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 |
system
library function?
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 than it used to be with v1.x, except on machines with low amounts of installed RAM. A disadvantage is that if you spawn a real-mode program that uses XMS, the
extended memory used up by your DJGPP program will be unavailable to it, unless you use a memory manager (as opposed to when CWSDPMI uses raw XMS or HIMEM). The only way around this problem is to
buy more RAM, or to install a real memory manager.
Note that if you use a memory manager such as EMM386 or QEMM386 with the NOEMS parameter, CWSDPMI will use the XMS (as opposed to VCPI) services to allocate extended memory, and will allocate all of the available XMS memory for itself. So if, while your DJGPP program runs, some resident software such as device driver or TSR will try to allocate XMS, the allocation will fail.
Q: How much stack space do I have in my program?
Q: My program seems to overflow the stack, but only when I run it under a debugger...
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 is going on??
_stklen
in your program. Example:
unsigned _stklen = 1048576; /* need a 1MB stack */The DJGPP startup code checks both the value in the stub info and the value of
_stklen
, and uses the larger of these two. Therefore, programs that are known to require large stack
size should set _stklen
to make sure they will always work, even if somebody stub-edits them to a lower value. This technique is also safer when you need to debug your program with
gdb
(see below). However, you might need to use STUBEDIT with programs for which you don't have the sources.
Programs which need an unusually large stack might crash with bogus stack traces, because part of the heap gets 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 and recompile the program. (Some DPMI hosts will actually allocate the entire 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 (e.g. if it has a wrong syntax).
When you run a program as an un-stubbed COFF image under a debugger, the stack size comes from the debugger. So if your program needs a large stack and you run it under gdb
, be sure
to stubedit gdb
to enlarge its stack to at least the value your program needs to run safely.
Under Windows, be sure you've allocated a sufficiently large swap file (let's say, 40MBytes) from the Windows' Control Panel, and 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 file DOSPRMPT.PIF
,
which almost surely defines very low limits on these two, and your program might have problems getting the memory it needs for its stack.
DJGPP v2.0 has a subtle bug in its startup code that is seen very rarely, and that manifests itself by a program crashing with Page Fault or SIGSEGV. If you are using v2.0 and enlarging the stack and the CWSDPMI heap size didn't help, try adding some (e.g., 4KB) static data to your program and see if that helps. But the best way to overcome this is to upgrade to DJGPP v2.01 or later.
| Previous | Next | Up | Top |
Q: I call my program with an argument x*y and it complains about something called xyzzy??...
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:
Note that *.* only picks up files that actually have an extension. This is contrary to the usual DOS practice where it means all the files, with or without extension.
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 |
__crt0_glob_function
and make it always return a NULL
pointer. See the documentation of this function in the library reference.
| Previous | Next | Up | Top |
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?
main
function (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 in order for them to be treated as literal characters. 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?). This is also different from what you get under a Unix shell.
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 |
Q: I have a Makefile of Unix origin which contains some very long command lines. Will it work with DJGPP?
This method is suitable only for invoking DJGPP programs from other DJGPP programs. You don't have to do anything special to use this method, it is all done automagically for you by the library
functions like system
, spawnXX
and execXX
on the parent program side, and by the start-up code on the child side.
Note: In case you wonder, the name !proxy comes from the the string which identifies the use of this method: instead of getting the actual command line, the program gets !proxy followed by the address of the actual command line.
system
library functions should be globbed by the child,
while the arguments passed by spawnXX
and execXX
family of functions should not; thus the former uses the environment method while the latter use the !proxy
method.
Note that this method makes @ special when it is the first (or the only) character of a command-line argument, which should be escape-protected if you want to use it verbatim (see how to pass the @ character).
| Previous | Next | Up | Top |
The above limit depends on the size of the transfer buffer, so check the size of the value recorded in the stub header of the parent program before you pass extremely long command lines to
its children. GCC is the first program you should worry about, because the linker (ld.exe
) usually gets long command lines from GCC (they include the list of all the object files and
libraries to be linked).
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. One easy way to get rid of redirection characters without losing their effect is to
use the redir program which comes with DJGPP. For example, the following command:
frobnicate foo.bar > myfile.tmpcan be re-written instead like this:
redir -o myfile.tmp frobnicate foo.barThe port of Make 3.75 which comes with DJGPP v2.01 doesn't call
COMMAND.COM
in the above cases, but rather emulates pipes and redirection internally, so upgrading to v2.01 will solve
such problems. If you think about using Make 3.75 with DJGPP v2.0, don't: invoking v2.0 programs from v2.01 programs will cause subtle and hard-to-debug problems due to incompatibilities between
these two versions regarding the methods of invoking child programs (in particular, v2.0 doesn't support the environment method of passing long command lines described above).
| Previous | Next | Up | Top |
as.exe
), or Gas called by GCC accepts AT&T syntax, which is different from Intel syntax. Notable differences
between the two syntaxes are:
$
; Intel immediate operands are undelimited (Intel push 4
is AT&T pushl $4
).
%
; Intel register operands are undelimited. AT&T absolute (as opposed to PC-relative) jump
/ call
operands are
prefixed by *
; they are undelimited in Intel syntax.
add eax, 4
is addl $4, %eax
in AT&T syntax.
The source, dest
convention is maintained for compatibility with previous Unix assemblers, so that GCC won't care about the assembler with which it is configured, as some of GCC
installations (on systems other than MS-DOS) don't use GNU Binutils.
b
, w
, and l
specify byte
(8-bit), word (16-bit), and long (32-bit) memory references. Intel syntax accomplishes this by prefixing memory operands ( not the opcodes themselves) with `byte ptr'
,
`word ptr'
, and `dword ptr'.
Thus, Intel mov al, byte ptr FOO
is movb FOO, %al
in AT&T syntax.
lcall/ljmp $SECTION, $OFFSET
in AT&T syntax; the Intel syntax is call/jmp far SECTION:OFFSET.
Also, the far return
instruction is lret $STACK-ADJUST
in AT&T syntax; Intel syntax is ret far STACK-ADJUST.
SECTION:[BASE + INDEX*SCALE + DISP]is translated into the AT&T syntax
SECTION:DISP(BASE, INDEX, SCALE)
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:fooFor a complete description of the differences, get and unzip the files named
as.iN
(where N
is a digit) from the
bnu27b.zip archive, then see 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 i386You will see a menu of Gas features specific to x86 architecture.
A guide is available which was written by Brennan Mr. Wacko Underwood; it describes how to use inline assembly programming with DJGPP and includes a tutorial on the AT&T assembly syntax. Check out the DJGPP inline assembly tutorial. Many people who used Intel syntax and then converted to the AT&T style say that they like the AT&T variant more. However, if you prefer to stick with the Intel syntax, download and install NASM, which is a free portable assembler. It is compatible with DJGPP and accepts a syntax which is almost 100% compatible with the Intel style.
| Previous | Next | Up | Top |
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.
.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 the phase of the moon is at the moment of assembly, use
.byte
constants.
| Previous | Next | Up | Top |
Alternatively, here is what you can do to make your code linkable with DJGPP programs:
.lib
library, then extracting them as COFF files.
Note: If you use MASM or LIB32, please post your experiences to comp.os.msdos.djgpp news group, so that I can 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 of the rules for protected-mode programming (see next question).
| Previous | Next | Up | Top |
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:
INT NN
instruction.
| Previous | Next | Up | Top |
.obj
or .lib
code with DJGPP
.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?
.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.
Note: Note that mixing object files from different compilers usually won't work either, even if they both are in the .obj
format.
Lately, an automated conversion tool called OBJ2COFF was written by the SPiRiT team, which can be used to convert .obj
object files and .lib
libraries to
COFF format, provided that the original .obj
files 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 DJ Delorie's ftp server. If you have any problems with it or questions about it, send them to its author, Rico or to George van Venrooij. Note that the authors of OBJ2COFF have explicitly prohibited commercial use, so you shouldn't use OBJ2COFF for converting commercial object files.
Another conversion tool you might try is EMXAOUT from the emx/gcc package. It also requires the code to be written for the flat-address memory model and will reportedly complain if you feed it with code written for segmented memory models. EMXAOUT is available from the SciTech Software FTP site. If you need, you should be able to compile it with DJGPP; however, a precompiled binary is available in the above archive. Or you can get EMXAOUT from the EMX archives and the RSX extender (for running EMXAOUT under DPMI) from the RSX archives.
Note that EMXAOUT produces object files in a.out format, whose support in DJGPP is not as full as that of COFF . For example, ld.exe
(as of Binutils 2.7) doesn't
support a.out object files inside .a
libraries, so you will have to link them as .o
files.
| Previous | Next | Up | Top |
.obj
files. Are you really sure there is
nothing I can do??
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 can probably also disassemble the code into a
source form and submit it to Gas). Now will you consider sticking with DJGPP? Please??...
| Previous | Next | Up | Top |
Q: A program written for a 16-bit compiler uses the MK_FP or _MK_FP macro, but DJGPP doesn't seem to have it. How should I port it?
#define far #define near #define huge #define _far #define _near #define _hugeAlternatively, you could add suitable
-D
switches to the GCC command line, like this:
gcc -Dfar -Dnear -Dhuge -c myprog.cMacros that create far pointers from the segment and offset (usually called
MK_FP
or _MK_FP
) are mostly used in 16-bit code to access certain absolute addresses on
memory-mapped peripheral devices, like the video RAM. These chores are done differently in DJGPP. Here's one possible way to express MK_FP
in DJGPP (courtesy of
Charles Sandmann):
#include <sys/nearptr.h> #include <crt0.h> void * MK_FP (unsigned short seg, unsigned short ofs) { if ( !(_crt0_startup_flags & _CRT0_FLAG_NEARPTR) ) if (!__djgpp_nearptr_enable ()) return (void *)0; return (void *) (seg*16 + ofs + __djgpp_conventional_base); }The above uses the DJGPP nearptr facility; if you prefer to use farptr functions (which are safer and work with all known DPMI hosts), you will need to rewrite the code that uses these macros, so don't bother writing a replacement for the macro itself. The details are described in Accessing absolute addresses, below.
Macros that extract the segment and the offset from a far pointer (called FP_SEG
and FP_OFF
) are required in 16-bit code to pass addresses in registers when calling
real-mode DOS or BIOS services, like functions of interrupt 21h. See How to call real-mode interrupt functions, which describes how that should be done in DJGPP; here,
too, you won't need to port the macros but instead rewrite the code that calls the DOS or BIOS service.
__dpmi_regs
structure (declared on the dpmi.h
header file) to set the register values, and library function
__dpmi_int
to invoke the interrupt service. For example, consider the following code snippet:
#include <dos.h> void _highcolor (void) { _AH = 0x10; _AL = 0x03; _BL = 0; geninterrupt (0x10); }
Note: This calls the video BIOS interrupt 10h to allow bright background colors to be used instead of blinking characters. DJGPP has a library function, called
intensevideo
, to do that, but let's assume we have reasons not to use it.
Here's one way to express this in DJGPP:
#include <dpmi.h> void _highcolor (void) { __dpmi_regs r; r.h.ah = 0x10; r.h.al = 0x03; r.h.bl = 0; __dpmi_int (0x10, &r); }Please read How to call real-mode interrupt functions, elsewhere in this document, for further details on how call real-mode services from DJGPP programs.
| Previous | Next | Up | Top |
int86
int86
or intdos
functions to invoke a
software interrupt?
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 |
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 (at least 2KB, 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, but it can be made as small as 2KB), 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 to 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 (however, it can never be less than 2KB, the size of the stub, because memory used by the stub is reused for the transfer buffer).
| Previous | Next | Up | Top |
__dpmi_simulate_real_mode_interrupt.
__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. This stack is locked and is 4KB-long for any handling done in protected mode (such as real-mode callbacks), and at least 512 bytes in size for interrupts reflected into real mode.
This is usually enough, but sometimes you'll need to use your own, larger stack, e.g., if you expect interrupts to nest, or if your handler needs a lot of stack space.
Note: The DPMI spec indicates that you should not use the default stack if your procedure/interrupt handler uses more that 60 bytes, or 1/8 of the total stack space available by default.
In these cases you should point SS and SP to a larger buffer which is in conventional memory (possibly part of the transfer buffer).
If SS:SP isn't zero, it will be used as the address of the stack for the interrupt handler, so if it points to a random location, your program will most certainly 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 a user-defined stack, it's easier to call the __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 function names!).
| Previous | Next | Up | Top |
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?
_dos_ds
macro (defined on
header file). This selector has base address of 0 and a limit of 1MB, so you can use it to access any address in the conventional memory, but the relatively large limit allows a buggy program to
overwrite portions of DOS memory.
Note: Original release of DJGPP v2.01 makes the limit of _dos_ds
be 4GB, which effectively disables memory protection when you use that selector. However, since no
memory outside the first 1MB is properly mapped into your program's address space without additional DPMI calls, and the DPMI host is then free to put memory-mapped devices, such as Weitek I/O space
or the linear frame buffer of an SVGA, on any address it sees fit, that huge limit is an unjustified security hole.
The advantage of _dos_ds
is obviously that you don't have to create it, and that it is good for accessing every region in the first MByte range.
_dos_ds
. For example, here's a code snippet to set up a
selector which provides access to 64KB of text-mode video memory at 0xB800:0000
, courtesy of Bill Currie:
int TxtVRAMSetupSelector (void) { static char selectorData[8] = { 0xff, 0xff, 0x00, 0x80, 0x0b, 0xf3, 0x40, 0x00 }; int screenSelector = __dpmi_allocate_ldt_descriptors (1); if (__dpmi_set_descriptor (screenSelector, selectorData) < 0) abort (); return screenSelector; }The advantages of this method are that (1) you can set up the selector limit such that it only covers the memory region that you need, thus protection of the rest of memory is retained; and (2) you may set the base address to point to the beginning of the specific memory region you need to access, so that you don't have to add the base address for every access, making the access faster. For details about the contents of the 8-byte selector descriptor, see the documentation of the
__dpmi_get_descriptor
function in the library reference Info file.
__dpmi_segment_to_descriptor
which is a wrapper
around that DPMI service. It is easier to use than the __dpmi_set_descriptor
function above, since you don't have to mess with the 8-byte descriptor buffer, but it always defines a
64KB limit by default. Here is an example of code which gets a selector to access 64KB of video RAM beginning at 0xA000:0000
:
short video = __dpmi_segment_to_descriptor(0xa000);Note that descriptors created by this function should never be modified or freed. For this reason, you should use this function sparingly. For instance, if your program needs to examine various real mode addresses using the same selector, you should allocate a descriptor and change the base using the
__dpmi_set_segment_base_address
library function instead of using
__dpmi_segment_to_descriptor
to allocate separate descriptor for each address.
header file. You should convert any real-mode
far pointer segment:offset pair into a linear address (i.e., segment*16 + offset), and use _dos_ds
or any other selector which allows access to conventional memory, like
this:
unsigned char value = _farpeekb(_dos_ds, segment*16 + offset);Use
_farpeekw
to peek at 16-bit shorts and _farpeekl
to peek at 32-bit longs. If you need to access several (non-contiguous) values in a loop, use the corresponding
_farnspeekX
functions which allow you to set the selector only once, as opposed to passing it with every call (but be sure the loop doesn't call any function that itself sets the
selector; see the library reference for more details).
There is a corresponding set of _farpokeX
and _farnspokeX
functions to poke (change the values of) such memory locations.
These functions have an advantage of emitting inline assembly code when you compile with optimizations, so they are very fast. See the library reference Info file for further details about these functions.
dosmemget
and dosmemput
library functions. They also require you to convert the segment:offset pair into a
linear address, but they don't need the conventional memory selector, as they can only be used to access the conventional memory (they use _dos_ds
internally).
Note that some memory-mapped peripheral devices might require 16-bit word accesses to work properly, so if dosmemXXX
yields garbled results, try dosmemXXXw
or "farptr"
functions.
_dos_ds
(e.g., created by one of the methods explained above), use the movedata
library function. It requires that you
pass a selector and an offset for both the conventional memory address and for the buffer in your program's address space. Use the _my_ds
function (note that it's a
function, not a variable!) to get the selector of any variable in your program, and use the address of the variable (cast to an int
) as its "offset" or linear address.
movedata
is fast because it moves by 32-bit longs, but be careful with its use when moving data to and from peripheral cards: some of them only support 8- or 16-bit wide data path, so
moving data 4 bytes at a time won't gain you much, and might even get you in trouble with some buggy BIOSes. The functions movedatab
and movedataw
are provided for
moving by bytes and by 16-bit words, respectively.
For example, here is a code snippet that combines one of the methods for allocating a descriptor for video RAM access with a call to movedata
to move a buffer to the graphics screen:
short video = __dpmi_segment_to_descriptor(0xa000); movedata(_my_ds(), buffer, video, 0, 320*200);
header; see the library
reference for more details. Also see the description of how to get the fastest direct access to peripheral devices, below.
| Previous | Next | Up | Top |
movedata
to pass data between my program and the transfer buffer, but get bogus values or General Protection Fault.
_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 |
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. Linux's DOSEmu and Win/NT won't allow you to set such a huge limit on the memory segment, because these operating systems
take memory protection seriously; in these cases __djgpp_nearptr_enable
will return zero--a sign of a failure. CWSDPMI, QDPMI, Win 3.x and Win 9x all allow this technique (OS/2 Warp
seems to allow it too, at least as of version 8.200), but some events break this scheme even for those DPMI hosts which will allow it. A call to malloc
or any other library function
which calls sbrk
might sometimes change the base address of the 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 a result of some other events external to the executing code thread, like multitasking or debugger execution.
You should also know that the __djgpp_nearptr_enable
function in DJGPP v2.0 didn't verify that the limit was properly set. So if the DPMI server would fail the call
silently, the function won't detect it and will not return a failure indication. DJGPP v2.01 corrects this omission by always verifying that the DPMI host has honored the request,
and returns a failure indication if it hasn't.
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".
Another possibility is to use the DPMI function 0x508
that can map any range of physical memory addresses into a block that you allocate. Note that this is a DPMI 1.0 functionality
which is not supported by most DPMI 0.9 hosts (CWSDPMI does support it). There is a helper function __djgpp_map_physical_memory
in the DJGPP C library
that you can use to call these services.
| Previous | Next | Up | Top |
__dpmi__XXX
wrappers in the DJGPP library.
| Previous | Next | Up | Top |
_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.
Here's a code fragment that shows how
to do this:
#include <dpmi.h> #include <go32.h> static __dpmi_regs callback_regs; static _go32_dpmi_seginfo callback_info; int install_mouse_handler (unsigned mask, void (*func)(__dpmi_regs *)) { __dpmi_regs r; callback_info.pm_offset = (long)func; if (_go32_dpmi_allocate_real_mode_callback_retf(&callback_info, &callback_regs)) return -1; /* failure */ r.x.ax = 0xc; r.x.cx = mask; __dpmi_int (0x33, &r); return (r.x.flags & 1) ? -1 : 0; }The handler (
func
in the above example) will be called with a pointer to a __dpmi_regs
structure which is filled by values found in the CPU registers when the mouse
driver calls the handler. See the docs in the library reference Info file for further details about allocating wrapper functions.
| Previous | Next | Up | Top |
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 caught by the DPMI host and passed to protected mode first; only if unhandled, they are then 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 should consider installing a real-mode interrupt handler in addition to the protected-mode one. Such a real-mode handler will be called before the interrupt gets to the DPMI host, and handle the interrupt entirely in real mode, so it must be written in assembly and located in conventional memory (below the 1MB mark). If you need to hook an interrupt with both PM and RM handlers, 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:
__dpmi_get_protected_mode_interrupt_vector
and save the structure it returns (to restore the previous handler address before your program exits).
__dpmi_lock_linear_region.
__dpmi_set_protected_mode_interrupt_vector
passing it the pointer to a __dpmi_paddr
structure filled with _my_cs
in the
selector
field and the address of your function in the offset32
field.
_go32_dpmi_XXX
functions instead of the bare-bones API wrappers whose names start with
__dpmi_.
Specifically:
_go32_dpmi_get_protected_mode_interrupt_vector.
This function puts the selector and offset of the specified interrupt vector into the pm_selector
and
pm_offset
fields of the structure pointed to by its second argument. This data should be saved and later passed to _go32_dpmi_get_protected_mode_interrupt_vector
to
restore the vector on exit.
_go32_dpmi_allocate_iret_wrapper,
passing it the address of your functions in the pm_offset
field and the value of _my_cs
in the
pm_selector
field. The pm_offset
field will get replaced with the address of the wrapper function which is a small assembler function that handles everything an
interrupt handler should do on entry and before exit (and what the code GCC generates for an ordinary C function doesn't include); the effect is similar to using interrupt or
_interrupt
keyword in some DOS-based compilers.
_go32_dpmi_chain_protected_mode_interrupt_vector.
This will set up a wrapper function which, when called, will
call your handler, then jump to the previous handler after your handler returns. Put the address of your handler into the pm_offset
field and the value of _my_cs
into
the pm_selector
field of the _go32_dpmi_seginfo
structure and pass a pointer to it to this function.
_go32_dpmi_set_protected_mode_interrupt_vector
with the address of the _go32_dpmi_seginfo
structure you got either from
_go32_dpmi_allocate_iret_wrapper
or from _go32_dpmi_chain_protected_mode_interrupt_vector.
The problem with writing handlers in C as above is that the wrappers' code and data aren't locked, and in practice you can't lock all of memory the handler itself uses, either. Thus, this approach is
generally unsuitable for production-quality software and should be used only when the program is known not to page (i.e., only the physical memory is used). You might consider disabling virtual
memory to make sure your program doesn't page. To accomplish this, either set the _CRT0_FLAG_LOCK_MEMORY
bit in the _crt0_startup_flags
variable, or use
CWSDPR0 or PMODE/DJ as your DPMI host. In fact, using one of these methods is the recommended way of debugging the first versions of a program that hooks hardware
interrupts; only after you are sure that your basic machinery works should you move to testing it in a setup when paging might happen.
Note that _CRT0_FLAG_LOCK_MEMORY
is only recommended for small programs that run on a machine where enough physical memory is always available, because the startup code currently
doesn't test if memory is indeed locked, and you can end up with unlocked, or partially unlocked memory, which will crash your program.
To install a real-mode interrupt handler, you do this:
__dpmi_get_real_mode_interrupt_vector
and save the structure it returns (to restore the previous handler address before your program exits).
__dpmi_allocate_dos_memory
and put the code of your handler there with the dosmemput
function. (You could also call one of
the functions which allocate a real-mode call-back, but these will cause a mode switch on every interrupt, which you want to avoid; otherwise there is no point in installing a real-mode handler,
right?)
__dpmi_allocate_dos_memory
returned into a __dpmi_raddr
structure (the lower 4 bits into offset16
field, the rest into
segment
field), then call __dpmi_set_real_mode_interrupt_vector.
For examples of installing and using hardware interrupt handlers, see the sample code written by Bill Currie, the Sound Blaster interrupt-driven functions, the mkkbd package, and the libhw library, described under sample DJGPP packages. Alaric B. Williams has written a tutorial on DJGPP interrupt handling.
| Previous | Next | Up | Top |
_go32_...
functions, but now comes v2 which also has __dpmi_...
functions. Are there any differences between these two
varieties?
Q: Do I need to convert my old v1.x code to use the new __dpmi_...
functions?
__dpmi_...
functions are just bare-bones wrappers of the DPMI API calls (see DPMI Specification), generally unsuitable for use with handlers written in C,
whereas the old _go32_...
functions are intelligent helper functions which only make sense if your interrupt handlers are C functions. The problem with the _go32_...
functions is that they don't lock all the code and data they (and your handlers) use, so they can crash on memory-tight machines and thus aren't suitable for production-quality code. But they are
certainly useful in the initial stages of writing and debugging code that hooks hardware interrupts, and for migrating existing v1.x code to v2. Some of the old names were just
#define'd
to the new names where the functionality is identical.
The bottom line is that it shouldn't be necessary to convert your code for it to work at least as well as it did in v1.x; but if you want it to be more stable, you should rewrite your handlers in
assembly and use the new __dpmi_...
functions (see How to install a hardware interrupt handler).
| Previous | Next | Up | Top |
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 systems).
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 many 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 the interrupt handler to some other place. Use a ring 0 DPMI server such as CWSDPR0 or PMODE/DJ which don't swap interrupt stacks--this will reduce the overhead of the interrupt reflection to some degree. 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, if
the _CRT0_FLAG_UNIX_SBRK
bit in the _crt0_startup_flags
variable is 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.
You should also keep in mind that the DPMI server can decide to handle some of the interrupts itself and not pass them to your program, although this is rare. For example, Win95 won't pass the
Ctrl-Alt-Del combination to your keyboard interrupt handler, but will rather act on it itself; QDPMI sometimes processes Ctrl-C presses so that your program never sees them, etc. Sometimes, but not
always, you can change some configuration option to make some keys get to your handler (e.g., the Alt-TAB setting on the Win3.x .PIF
file).
If the above still doesn't explain your problem, then post your code on comp.os.msdos.djgpp news group or the djgpp mailing list, tell there how it fails and somebody will usually have a solution or a work-around for you.
| Previous | Next | Up | Top |
inp
and outp
functions. But I hear they aren't available in DJGPP?
#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.
Q: How can I reference C variables from my inline assembly code?
info gcc "C Extensions" "Extended Asm"(Note the quotes: they are important.) You will, of course, need that the stand-alone info reader be installed on your system for the above command to work. If it is not already installed, get the file
txi390b.zip
from the DJGPP distribution and install it. If you read this FAQ via WWW, you can also read about the GCC inline assembly extensions with your Web browser.
| Previous | Next | Up | Top |
Q: Can I write commercial programs with DJGPP?
libiostr.a
) and the Standard Template Library (libstdcx.a
) which come with DJGPP allow you to use them 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).
Only the library of additional C++ classes (libgpp.a
) 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.) 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 are not as powerful, but are free from any restrictions).
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.
Note that the above says nothing about the legal aspects of contributed packages, like GRX and others; you will need to read their docs to find out.
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?
When you redistribute 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 that 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 | Top |
| Previous | Next | Up | Top |
| Previous | Next | Up | Top |
subscribeIf 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 the djgpp-announce by sending message to the list server which says so:djgpp
subscribeThe announcements which go to djgpp-announce get reflected to djgpp, so you don't need to subscribe to both these lists.djgpp-announce
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:
subscribeordjgpp-digest-daily
subscribeNote that some mailers reject messages with too large size, so you might have trouble with the weekly digest. If you subscribe to it and don't get the digest, try the daily one instead, or switch to another mail software.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 the 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 news group instead of subscribing to the mailing list, so that the load on DJ's list server will get lower. There is also a possibility of reading the news group (but not posting to it) through the Mercury Gopher server at Michigan State University
| Previous | Next | Up | Top |
Q: I've been trying for days to unsubscribe from the djgpp mailing list. What am I doing wrong?
unsubscribeWhen you unsubscribe, that stops new messages from being sent to you. Messages that are already in the mail queues of various mail programs between the DJGPP list server and the machine where you receive your mail--cannot be stopped. Therefore, allow some time before you decide that your unsubscribe message didn't work. In extreme cases, when one of the machines that are forwarding mail to you is down, you can get the messages upto 5 days after you've unsubscribed.djgpp
If you think you have waited enough and the messages still keep coming, write to listserv administrator 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.
Recently, DJ has added a mail archive browser to his Web site. With this tool, you can list and read the messages by year, month and day, as well as search the last few days for something you might have missed. This service is available via World-Wide Web.
| Previous | Next | Up | Top |
If you subscribe to the weekly digest, then the problem might be that your mailer rejects the huge message size. Try the daily digest, or switch to another mailer, and see if that helps.
| Previous | Next | Up | Top |
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 have also 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 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 problem is caused by excessive load on the list server, so everybody who can please switch to reading the comp.os.msdos.djgpp news group and unsubscribe from the list.
| Previous | Next | Up | Top |
If you want to help in further v2 development, check out the list of features which have yet to be done and volunteer to implement some of them.
main
functions is 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 applications load much faster.
.dxe
files?
| Previous | Next | Up | Top |
Q: How do I fix a bug/add a feature to one of the DJGPP programs?
*s.zip
in the DJGPP distribution. The C Library sources are in djlsr201.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:
All sources are shipped in ready-to-build form. Any diffs that come with the source distribution, like the files in the diffs/
directory, have already been applied, and any
configuration scripts and/or batch files have been run.
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 standard here is that different packages were
ported to DJGPP by different people, as best as they saw fit.) After you've successfully built the program, make your fixes and build the program the same way you did before.
Note that generally to build these programs, you must have the GNU Make program, and some makefiles require that you
install additional utilities, like Sed ftp.simtel.net/pub/simtelnet/gnu/djgpp/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, or 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. The port of Make 3.75 and later can be built so that it doesn't issue FP instructions, but you will have to get the sources and recompile Make first, as the stock version wasn't configured in that way.
If you think that you found a bug in one of the programs or libraries written for DJGPP (e.g. the C library, CWSDPMI, symify, etc.) be sure to check the list of known bugs. If your bug is not there, you can later submit it to the bug-tracking system. Before you submit a bug report, please make every effort to verify that your bug is not caused by incorrect usage, or by problems in your DJGPP installation. Reports such as "All DJGPP programs crash" or "I cannot compile any program" are clearly not bugs, because these things work for many hundreds of DJGPP users every day. If you can investigate the cause of the bug and find a solution that makes it go away, submit a bug report with all the details. If you cannot find the cause(s), I suggest posting your problem description to the news group and asking people to verify that it is indeed a bug, before you submit a bug report. The bug-tracking system includes a list of all known bugs, many of them with solutions or work-arounds; please check them before creating a new bug report.
| Previous | Next | Up | Top |
Here is a 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 |
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??
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 program's stub info block
and 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=dj1Voila! Now, when you run dj2, it tells the stub to load the image of dj1, but pass "dj2" in
argv[0].
If you use the DJGPP port of GNU Fileutils 3.13 or later, the ln program there can do the above steps for you if you say this (like on Unix):
ln -s dj1.exe dj2.exe
| Previous | Next | Up | Top |
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 dpmip1.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.
You can also browse the DPMI spec on-line.
| Previous | Next | Up | Top |
To visit, point your Web browser to the DJGPP Web site.
| Previous | Next | Up | Top |
Q: I found and corrected a bug in one of the programs distributed with DJGPP. Where should I put it?
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.
If you decide to upload, please send mail to the djgpp-announce list with a brief description of your program/patch. (The message will get reflected to both the news group 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 want to get such announcements and nothing else.)
If your program is more than a patch or a beta version, you might consider uploading it to the DJGPP archives on SimTel.NET. 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.NET mirrors throughout the world, which makes it easier to get.
DJ Delorie requests that all contributed packages uploaded to his server be source-only distributions; don't bother to include libraries or pre-compiled binaries, since DJ deletes them when he opens the zip archive. This is so there will be no danger of distributing programs infected by a virus (as there are no 32-bit virus-scanners yet). Please avoid uploading self-extracting archives because DJ extracts them on a Unix machine which can't run DOS executables.
| Previous | Next | Up | Top |
Q: I want to build GCC as a Unix-to-DOS cross-compiler. What should I do?
An RPM (Redhat Package Maintenance) distribution of the Linux to DOS cross-compiler is available, which is based on DJGPP v2.01 and includes everything you need to create DJGPP binaries on Linux (without running DOSEmu). This package has been built by James Soutter using the instructions below; you will need Linux and RPM 2.2.7. The RPM packaged cross-compiler is available from Redhat site; the sources are also available.
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.)
First, use the original FSF distributions for Gcc and Binutils, not the source distributions from DJGPP. That's because the DJGPP archives have sources patched to compile on MS-DOS and sometimes omit files that aren't necessary for DJGPP. In particular the GCC sources lack many files that the MS-DOS build doesn't need, to conserve space.
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-binutils cd X/dos-binutils configure --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 cp ld.new /usr/local/i386-go32-msdos/bin/ld cd ../../.. mkdir X/dos-gcc cd X/dos-gcc configure --target=i386-go32-msdos # Note: this produces errors building libgcc.a. Ignore them. # The libraries will come from the cross-compiler kit. 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/cppUnzip the DJDev and Gcc distributions in, say, /usr/local/djgpp. Ideally, build libgcc.a on a DOS machine, or get it from the
djcrx200.zip
archive. 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.
You might need to insert these two lines at the beginning of stubify.c
:
That's it! To build a program for DOS, say something like this:#include <sys/types.h>
#include <unistd.h>
gcc-dos hello.c -o hello.exe
| Previous | Next | Up | Top |
i = 0xfe+0x20;
Ain't it silly that such a great compiler would fail so miserably?
| Previous | Next | Up | Top |
Q: I have a program that reads struct contents from a binary file. It works OK when compiled with BC, but reads garbage when compiled with DJGPP. This must be a bug in DJGPP, right?
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:
Note: Note that this still allows the struct to be padded at the end, though.
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 a 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 with 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). Alternatively, you
could declare any single structure to be packed, like so:
struct { char name[7]; unsigned long offset; double quality; } __attribute__ ((packed));However, note that the latter will only work when you compile it as a C source; C++ doesn't allow such syntax, and you will have to fall back to declaring each struct field with the packed attribute. Therefore, it's best to only use declarations such as above if you are certain it won't be ever compiled as a C++ source.
The padding of struct fields should be considered when you read or write struct content from or to a disk file. In general, this should only be done if the file is read and written by the same
program, because the exact layout of the struct fields depends on some subtle aspects of code generation and the compiler switches used, and these may differ between programs, even if they were
compiled by the same compiler on the same system. If you do need this method, be aware of the struct field padding and don't assume that the number of the file bytes that the structure uses is equal
to the sum of the fields' sizes, even if you instructed the compiler to pack structs: GCC still can add some padding after the last field. So always use sizeof struct foo
to read and
write a structure.
Another problem with porting programs that read structs from binary files is that the size of some data types might be different under different compilers. Specifically, an int
is
16-bit wide in most DOS-based compilers, but in DJGPP it's 32-bit wide.
The best, most robust and portable way to read and write structs is through a char
buffer, which your code then uses to move the contents into or out of the struct fields, one by one.
This way, you always know what you are doing and your program will not break down if the padding rules change one day, or if you port it to another OS/compiler. The ANSI-standard
offsetof
macro comes in handy in many such cases.
| Previous | Next | Up | Top |
struct ffblk
from the header dir.h
in a C++ program, I get garbage in some fields of the structure!
__attribute__((packed))
directives, so the structures end up being not packed. DJGPP
v2.01 comes with GCC 2.7.2.1 which corrected that bug, so upgrade. As a work-around, surround the declaration of the structure that needs to be packed with #pragma pack
, like this:
#ifdef __cplusplus #pragma pack(1) #endif . . . #ifdef __cplusplus #pragma pack() #endif
| Previous | Next | Up | Top |
Q: Other DOS compilers supply a function named harderr
or _harderr
to hook the critical-error interrupt 24h, but DJGPP doesn't seem to have these...
AL
register to 3 and do an
IRET
, thus silently failing the DOS call that triggered Int 24h. The DJGPP startup code also hooks the protected-mode Int 24h with a handler that fails the DOS call as described
above. So in most circumstances you won't see that DOS prompt at all; your program will just see a failed DOS call.
However, some DPMI hosts (notably, QDPMI), will sometimes crash your program if it generates Int 24h, for instance when you access an empty floppy drive. In such cases, or when the default action of
failing the DOS call is not good enough, you will have to hook Int 24h with your handler. This should be done in exactly the same manner as hooking hardware interrupts (see
how to set an interrupt handler), because Int 24h is one of the few software interrupts that, like all hardware interrupts, are always reflected to the
protected-mode handler first. Note that CWSDPMI
currently doesn't support hooking Int 24h; if you set an interrupt handler, it won't be called.
There are ways to avoid program crashes due to Int 24h (under those DPMI hosts that exhibit this buggy behavior) other than to install a handler for it. For instance, you can test if the floppy
drive is empty with a BIOS call before accessing it with DOS functions; there are also similar ways to check if a CD-ROM drive is empty. The library function getmntent
(See
the "getmntent" section of the "libc.a reference".) can be used to detect all the drives that can be safely accessed by
DOS; or you can borrow some of the internal functions used by getmntent
from the library source distribution.
| Previous | Next | Up | Top |
go32-v2.exe
program?
go32-v2
program does the following:
go32
did in v1.x.
go32-v2 myprog
go32.exe
and put on your PATH
before the v1.x go32.exe
, it can also run a v1 COFF images, by loading the v1.x go32
and
letting it do the job. With this setup, you can run v2 programs from v1.x programs, because the v1.x program will load go32-v2
(since it found it first on the PATH) which knows how to
run v2 images, instead the original go32
which cannot.
| Previous | Next | Up | Top |
Q: Can I make a DLL using the DXE support?
Q: Where can I find information or examples about writing/loading the DXE files?
The only place you can find some docs and examples of writing and using a DXE is in the file djtst201.zip
in the
DJGPP "tests" distribution. The example there is exceedingly simplistic, but then so is the entire DXE
mechanism...
| Previous | Next | Up | Top |
Q: Why does Make behave as if some of the files were not there?
ALongFileName.cc
(because the Makefile tells it to build ALongFileName.o
), make sure there indeed is such a file in the directory. Sometimes people use archive tools (like
PKZIP
) that truncate long names, even on Win95, when they open an archive, which leaves you with names like alongfil.cc
, which is not the same as the original name when
LFN is supported. Be sure to use archivers that support long filenames, e.g. use DJTAR when you open .tar.gz
archives, or rename all the files to their original long names
after you open the archive.
If the problems persist even though the filenames are correct, upgrade to DJGPP v2.01 or later, where all programs should support long filenames properly. If you cannot upgrade, you will have to
disable LFN support (set LFN=n from the DOS prompt, setting it in DJGPP.ENV
does not always work in DJGPP v2.0).
| Previous | Next | Up | Top |
makefile:10: *** missing separator. Stop.Now what kind of excuse is that?
There are editors that replace TABs with spaces, so even a Makefile that used to work can become unworkable if you edit them with such an editor.
Another, more rare, cause of the above error message is if you use static pattern rules (with the %
character) incorrectly. Read the documentation that comes with Make carefully and
try to find the error.
| Previous | Next | Up | Top |
zoneinfo
directory?
zoneinfo
with a lot of small files that take up 3.5MB of my disk space. What are they for? Can I delete
them?
You might wonder why we need all these zoneinfo files when the UTC offset is required. Well, the simplest way to tell programs what the UTC offset is, is to have the user specify a single
number which is the offset; but then this number needs to be changed twice a year, to accommodate for the daylight saving time. Another, not-quite-so-simple way is to have the user specify the
current UTC offset and the DST rules; but this is a tedious and error-prone process, and many users get it wrong. Both of these methods have the drawback that if the rules change, programs
misinterpret old time-stamps, since they treat them according to new rules. Using a table that is read from a file and includes the offset calculation rules for every year avoids all these problems
and requires the user to point the TZ
environment variable to the file that is pertinent to his/her time zone, which is easy:
set TZ=c:/djgpp/zoneinfo/israelor
set TZ=c:/djgpp/zoneinfo/us/alaskaTo find the rule suitable for your location, look into the
src
subdirectory of zoneinfo
and browse the file whose name is your continent/part of the world. If no binary
file exists with the name of your zone, you can create one with using the time-zone compiler zic, whose source is also in the src
subdirectory.
A public domain time-zone database exists, and is updated from time to time with the latest world-wide changes to the offset calculation rules. (The rules change because politicians in different
countries make laws that change the local clock settings.) The contents of the zoneinfo
directory which comes with DJGPP is based on this database, but if you want the latest rules, you
can download them from the net as tzdata*.tar.gz
; tzcode*.tar.gz
in the same directory includes the programs that can be used to
generate the offset tables from their source in tzdata*.tar.gz
, the latest implementations of POSIX library functions that use time-zone information, and the man pages that document the
rules and the software. The last update as of this writing was in May 1996.
On any single machine, you don't need more than a single file from that directory, which is the file for your time zone; once you find that file, you can safely delete the rest. But if you distribute a program that uses the TZ setting, you will have to include all of the files, or tell your users how to get and install them.
faqNNNs.zip
on DJ Delorie's server and on SimTel.NET 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 faqNNNb.zip
from DJ Delorie's server or
from SimTel.NET mirrors. Currently, this includes the Info version, the text (ASCII) version and an HTML version as a single
large .html
file. More formats will be available as the tools for their generation are developed/tested. If none of these formats is good enough for you, here are some tools available to generate the FAQ list in other formats. If you know about any format not mentioned below that can be generated using widely available tools, please drop me a note so I could update this list and consider that format or those tools for inclusion in a future release of the FAQ. If you develop any such tools, consider uploading them to a site where they will be publicly available, and tell me about that site.
Note that the FAQ source is a heavy user of the Texinfo macro facility, so any conversion program that doesn't support Texinfo macros will probably have hard time coping with the FAQ. When confronted with this problem try feeding the converter with the macro-expanded version of the FAQ (the Makefile in the source distribution has a special target for such cases).
A program called Makertf can reportedly be used to convert a Texinfo sources of this FAQ to the Rich File Format which can then either be browsed by an RTF browser (such as Adobe Acrobat) or converted into a Windows Help file with a Windows Help compiler. Makertf is available from CCT mirrors. The Windows Help Compiler is available via anonymous ftp from the Microsoft ftp site.
There also a program called INFNG that can be used to convert the Info (not Texinfo) version of the FAQ to the Norton Guide format. INFNG can be downloaded from the DJGPP archive.
This FAQ is Copyright (C) 1994, 1995, 1996, 1997 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/news group 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:
John M. Aldrich Anthony Appleyard John Bodfish Francois Charton Bill Currie Bill Davidson DJ Delorie Tom Demmer Juergen Erhard Jeremy Filliben James W. Haefner Koen Van Herck Robert Hoehne Gordon Hogenson Harry Johnston Martynas Kunigelis Pieter Kunst Y. Lazarovitch Alexander Lehmann Marty Leisner Dave Love Rob Nader Eric Nicolas Elliott Oti Esa A E Peuha Walter Prins Steve Salter Charles Sandmann Terrel Shumway Andrew Szymkowiak Launey Thomas Chris Tilbury Stephen Turnbull Santiago Vila Ronan Waide Morten Welinder Anthony Edward Wesley Mark H. Wood