www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/01/28/19:46:02

From: "John M. Aldrich" <fighteer AT cs DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: why won't my .exe program run properly until I set env var?
Date: Wed, 28 Jan 1998 19:35:15 -0500
Organization: Two pounds of chaos and a pinch of salt.
Lines: 123
Message-ID: <34CFCEC3.6C89@cs.com>
References: <spark-2901980201090001 AT p113-thalia DOT es DOT co DOT nz>
NNTP-Posting-Host: ppp213.cs.com
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

Zippy wrote:
> 
> I am new to DJGPP, so this might be a dumb q, but here it goes...
> 
> I run DJGPP within a DOS window in Windows95.  I've got a batch file which
> sets the path and the environment var.  So the procedure I take to use
> DJGPP is
> 1. Start up a DOS window from windows95
> 2. Run the batch file (which has
> set djgpp=c:\djgpp\djgpp.env
> set path=c:\djgpp\bin;%path%)
> 3. Start programming

This is silly.  If you plan to do a lot of programming in DJGPP, you
should set the environment variables in your autoexec.bat so they always
exist.  I can't think of any possible reason why this wouldn't work
better.

> OK, I wrote a very short program that renames a file.
> 
> #include <stdio.h>
> 
> main(int argc, char *argv[])
> {
>    char *d, *p, *n, *e;
>    int dummy = fnsplit(argv[1], d, p, n, e);
>  /* This splits a filename into drive, path, name and extension. */
> 
>    dummy = rename("oldname.txt", strcat(n, ".txt"));
> }

You've got one serious problem right here:  you never allocate memory
for any of those pointers.  Since they are uninitialized, fnsplit() and
strcat() attempt to write to any old random memory locations and almost
certainly crash as a result.

This is basic C here, not a DJGPP-specific question.  Pointers are not
the easiest concept of C to grasp, but I don't understand why you
thought they were needed in the first place.  The following would have
worked:

    char d[MAXDRIVE], p[MAXDIR], n[FILENAME_MAX], e[MAXEXT];

If you'd looked at the documentation for fnsplit() a bit more carefully,
you'd have noticed that it says specifically that you need to provide
buffers to store the data, and it even provides the above constants to
use for the sizes.  (Actually, FILENAME_MAX is defined by stdio.h, but
you need to use it because MAXFILE might not be long enough to hold the
filename plus the extension.)

Also, it looks like the only item from fnsplit() that you are actually
using is the filename itself, so why even bother with the other
parameters?

    fnsplit( argv[1], NULL, NULL, n, NULL );

This works just as well and makes the purpose of the program clearer.

Another style issue:  it's not necessary to store the return value of a
function if you don't need it.  'dummy' in your program is not only
worthless (since you never check it), but it makes the program less
clear.

> The idea was to pass the new filename to the .exe program and rename the
> file "oldname.txt" into the new one.
> 
> I compiled the program by typing in
> 
>     gcc nameit.c -o nameit.exe

Try adding the '-Wall', '-O', and '-g' switches to your command line. 
The additional warning and debugging information they provide can be
priceless.  For example, here's the output that resulted when I compiled
your program:

[WIN] D:\TEMP>gcc -Wall -O -g -o temp.exe temp.c
temp.c:4: warning: return-type defaults to `int'
temp.c: In function `main':
temp.c:6: warning: implicit declaration of function `fnsplit'
temp.c:9: warning: implicit declaration of function `strcat'
temp.c:9: warning: passing arg 2 of `rename' makes pointer from 
integer without a cast
temp.c:5: warning: `d' might be used uninitialized in this function
temp.c:5: warning: `p' might be used uninitialized in this function
temp.c:5: warning: `n' might be used uninitialized in this function
temp.c:5: warning: `e' might be used uninitialized in this function
temp.c:10: warning: control reaches end of non-void function

In addition to the major bug I described above, this also reveals that
you forgot to #include the header files that declare fnsplit() and
strcat() (dir.h and string.h, respectively), and that it's not good
programming practice to omit a function's return type.  The last warning
tells you that you forgot to put a 'return' statement at the end of
main().

> Now I run the program by typing in
> 
>    nameit newname
> 
> and the old file is rename to "newname.txt"  The program works.

It shouldn't.  Probably there were some garbage values in the stack
frame left by the C runtime code that just happened to point to valid
addresses within your program when you ran it.

The most likely reason for the crash when the DJGPP environment variable
was defined is that the environment loading code left some other values
in the stack that were not valid addresses, and therefore caused the
crash.

> Now, this is what I don't understand.  Why do I need to set the variable
> when I am running the stand-along .exe file?

You don't.  The fact that it crashed one way and not the other is total
coincidence (albeit strange).  :-)

-- 
---------------------------------------------------------------------
|      John M. Aldrich       | "Autocracy is based on the assumption|
|       aka Fighteer I       | that one man is wiser than a million |
|   mailto:fighteer AT cs DOT com   | men.  Let's play that over again,    |
| http://www.cs.com/fighteer | too.  Who decides?"   - Lazarus Long |
---------------------------------------------------------------------

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019