burleigh@cica.cica.indiana.edu (Frank Burleigh) (12/07/89)
Please observe the following (reduced) function and, below it, a function returning pointer to char, which it calls: void mark_cmp( char flag ) { int i; unsigned memleft; char sav_str[13], *p, *q; newfblk **f; ... f = fp; memleft = coreleft(); for( i = 0; i < files; i++ ) { if( !((*f)->f_attrib & FA_DIREC) ) { p = (*f)->f_name; q = make_fn( p ); /*<big problems right here*/ ... } f++; } ... } char *make_fn( char * file_name ) { int i; char *w, *p = file_name; char name[13]; for( w = name; *p; p++ ) if( *p != ' ' ) *w++ = *p; /*don't copy ws*/ *w = '\0'; return name; } make_fn receives a pointer to a file name prepared for display, that is, with spaces: fn .ext and changes it to 'fn.ext.' The result is fine as it leaves make_fn, but when we get back to mark_cmp, the string has been destroyed. You may see only part of the name followed by garbage (part of the name is lost), or you may see the full name, but with trailing garbage, as though the terminating null got lost. I've tried a few modifications, to no avail. I had handy a global string sufficient to hold the result, and so to continue I have used that within make_fn instead of 'name', and returned a pointer to that. That works fine. The program is compiled with TC 2, small model. I really doubt I've filled up the data segment, but don't have any way to prove it (read: *I* don't know how to tell how much memory is unallocated in the data segment). If people suspect a memory allocation problem, I might report that coreleft shows around 32K left. I don't know that that is within the data segment. (What sort of memory does coreleft report as "free?") As long as I'm talking about memory, I might also complain that I've had problems using TC malloc before; that is, I've had experiences where I'd allocate a block of size N, put stuff in it, then go to show it and find some junk in the space. In all cases conversion to calloc fixed that problem. Am I alone in this? But this is really a side complaint... Please, fill my mbox with your ideas about why an apparently good string upon exit from make_fn turns bad on return to mark_cmp. Thanks muchly. -- Frank Burleigh burleigh@cica.cica.indiana.edu USENET: ...rutgers!iuvax!cica!burleigh BITNET: BURLEIGH@IUBACS.BITNET Department of Sociology, Indiana University, Bloomington, Indiana 47405
Ralf.Brown@B.GP.CS.CMU.EDU (12/07/89)
In article <272@cica.cica.indiana.edu>, burleigh@cica.cica.indiana.edu (Frank Burleigh) wrote: >char *make_fn( char * file_name ) >{ > char name[13]; > > return name; >} >make_fn, but when we get back to mark_cmp, the string has >been destroyed. You may see only part of the name followed That's because you are returning the address of a variable which ceases to exist as soon as you leave the function. What you need is static char name[13] ; -- UUCP: {ucbvax,harvard}!cs.cmu.edu!ralf -=-=-=-=- Voice: (412) 268-3053 (school) ARPA: ralf@cs.cmu.edu BIT: ralf%cs.cmu.edu@CMUCCVMA FIDO: Ralf Brown 1:129/46 FAX: available on request Disclaimer? I claimed something? "How to Prove It" by Dana Angluin 13. proof by reference to inaccessible literature: The author cites a simple corollary of a theorem to be found in a privately circulated memoir of the Slovenian Philological Society, 1883.
bobmon@iuvax.cs.indiana.edu (RAMontante) (12/07/89)
burleigh@cica.cica.indiana.edu (Frank Burleigh) <272@cica.cica.indiana.edu> :
-
-char *make_fn( char * file_name )
-{
- int i;
- char *w, *p = file_name;
- char name[13];
-
- for( w = name; *p; p++ )
- if( *p != ' ' )
- *w++ = *p; /*don't copy ws*/
- *w = '\0';
- return name;
-}
Your `name[]' array is an automatic variable, created on the stack.
Thus it is guaranteed to be valid *only while make_fn() is active*.
Once control returns to the caller that storage may be legally trashed.
This isn't peculiar to Turbo C, it's a property of C itself (and of most
languages that can distinguish between "temporary" local storage and
"permanent" global storage).
Library functions such as ctime() avoid this same problem by making the
string storage be static data. Such storage stays put, until a
subsequent function call overwrites it. Another choice is to let the
caller supply the workspace --- this works better when the new string is
of varying length.
Try this:
char *make_fn( char * file_name )
{
static char name[13], *w;
for( w = name; *file_name; file_name++ )
if( *file_name != ' ' )
*w++ = *file_name; /* copy only non-blanks */
*w = '\0';
return name;
}
leo@dduck.ctt.bellcore.com (Leo Zvenyatsky) (12/07/89)
In article <272@cica.cica.indiana.edu> burleigh@cica.cica.indiana.edu (Frank Burleigh) writes: > ... >char *make_fn( char * file_name ) >{ > int i; > char *w, *p = file_name; > char name[13]; > > for( w = name; *p; p++ ) > if( *p != ' ' ) > *w++ = *p; /*don't copy ws*/ > *w = '\0'; > return name; >} > ... stuff deleted ... Sorry for posting - mail bounced. The problem is that name[] is NOT static (it is dynamic) and IS local to make_fn. When make_fn returns, all of its dynamic storage is returned to the free pool and may or may not be overwritten by anything else. The point is that you CANNOT trust it! The simplest solution is to declare name[] static, i.e. char static name[13]. Another solution is to pass to it a char pointer pointing to a storage within the CALLING routine, and have make_fn populate that array. Since calling routine has not yet completed, all of its storage is still intact. Hope that helps. _ ___ | If any views or opinions are found _// / | in this article, please return to: / _ __ / | Leo Zvenyatsky /___ </_(_) /__ o | ...bellcore!ctt!leo