quan@sol.surv.utas.oz (Stephen Quan) (09/30/90)
Hi, I'm the original poster (stephen quan@sol.surv.utas.edu.au), and I wish to make some more comments on 'life after free'. From: wuxing@comp.mscs.mu.edu (Xing Wu) >In article <quan.654410256@sol> you write: >> tmp = (char *) malloc(100); >> for (i=0; i<=99 ; i++) *(tmp+i) = ch; >> free(tmp); >> return tmp; > >>Any comments on free-ing tmp before it is return-ed? > >You mean, other than "why?" >According to my manpage, free makes the space "available for further >allocation, but its contents are undisturbed." > >This would lead me to believe that, depending on the compiler, and >depending on your OS, and depending on the phase of the moon, the >pointer would still point to the buffer you malloc'ed. Maybe. I interpreted the MAN page just the same. However, I was hoping that the man page implied that the memory contents is still valid for at least one instruction more. Why? I'll tell you in a sec ... >Is there any particular reason you don't return the pointer, use >it, and then free it? I normally do what you suggest, the reason why a brought up this issue is that if what I propose wasn't so unpredictable then I can have something like : printf("%s\n",funny('c')); printf("%s\n",funny('x')); Where funny will create a string of 100 c's or 100 s's. The string is displayed in 'printf' (hopefully) and you don't need to worry about free-ing the memory. (For keen programmers, the C definition for funny up-up above is not quite correct, but I think you get the picture, anyway. ie missing 0 string terminator.). stephen quan@sol.surv.utas.edu.au
dylan@ibmpcug.co.uk (Matthew Farwell) (09/30/90)
In article <quan.654673946@sol> quan@sol.surv.utas.oz (Stephen Quan) writes: > From: wuxing@comp.mscs.mu.edu (Xing Wu) > >In article <quan.654410256@sol> you write: > >> tmp = (char *) malloc(100); > >> for (i=0; i<=99 ; i++) *(tmp+i) = ch; > >> free(tmp); > >> return tmp; > I normally do what you suggest, the reason why a brought up this issue is > that if what I propose wasn't so unpredictable then I can have something > like : > > printf("%s\n",funny('c')); > printf("%s\n",funny('x')); > > Where funny will create a string of 100 c's or 100 s's. The string is > displayed in 'printf' (hopefully) and you don't need to worry about > free-ing the memory. Forgive me if I'm wrong, but whats wrong with doing .... char * funny(c) char c; { static char a[100]; int i; for (i=0 ; i<99 ; i++) a[i] = c; a[99] = '\0'; return (&a[0]); } Dylan. -- Matthew J Farwell | Email: dylan@ibmpcug.co.uk The IBM PC User Group, PO Box 360,| ...!uunet!ukc!ibmpcug!dylan Harrow HA1 4LQ England | CONNECT - Usenet Access in the UK!! Phone: +44 81-863-1191 | Sun? Don't they make coffee machines?
karl@haddock.ima.isc.com (Karl Heuer) (10/02/90)
In article <quan.654673946@sol> quan@sol.surv.utas.oz (Stephen Quan) writes: >I normally do what you suggest, the reason why a brought up this issue is >that if what I propose wasn't so unpredictable then I can have something >like : > printf("%s\n",funny('c')); > printf("%s\n",funny('x')); Bad idea, even under the old rules. This depends on the funny-buffer retaining its contents until printf() copies it into the stdio buffer. So it will break if malloc() is called by printf() or any of the stdio routines it calls--which is sometimes the case. I generally recommend temp = funny('c'); printf("%s\n", temp); free(temp); instead. If you have enough of these that it's painful, consider writing your own allocation package on top of malloc()/free(), and include a function that will garbage collect the temporaries. Shouldn't be difficult. Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
burley@world.std.com (James C Burley) (10/02/90)
In article <1990Sep30.163824.12974@ibmpcug.co.uk> dylan@ibmpcug.co.uk (Matthew Farwell) writes: In article <quan.654673946@sol> quan@sol.surv.utas.oz (Stephen Quan) writes: > From: wuxing@comp.mscs.mu.edu (Xing Wu) > >In article <quan.654410256@sol> you write: > >> tmp = (char *) malloc(100); > >> for (i=0; i<=99 ; i++) *(tmp+i) = ch; > >> free(tmp); > >> return tmp; > I normally do what you suggest, the reason why a brought up this issue is > that if what I propose wasn't so unpredictable then I can have something > like : > > printf("%s\n",funny('c')); > printf("%s\n",funny('x')); > > Where funny will create a string of 100 c's or 100 s's. The string is > displayed in 'printf' (hopefully) and you don't need to worry about > free-ing the memory. Forgive me if I'm wrong, but whats wrong with doing .... char * funny(c) char c; { static char a[100]; int i; for (i=0 ; i<99 ; i++) a[i] = c; a[99] = '\0'; return (&a[0]); } Dylan. -- Matthew J Farwell | Email: dylan@ibmpcug.co.uk The IBM PC User Group, PO Box 360,| ...!uunet!ukc!ibmpcug!dylan Harrow HA1 4LQ England | CONNECT - Usenet Access in the UK!! Phone: +44 81-863-1191 | Sun? Don't they make coffee machines? It fails if you then do something like: printf("%s %s\n",funny('a'),funny('b')); On the practical side, one might want to use a statement like the above frequently as a debugging/testing feature in a program, where conciseness and "lack of interference" with the surrounding production code is a must. Yet the above statement (using two invocations of funny in one call, hence overwriting the results of one call with the results of the other, in effect, before invoking printf itself) might occur frequently. So, if you need to have some function like "funny" that you expect to reside in printf or similar calls, and there might be more than one, and you are willing to "assert" to yourself that there are never more than, say, eight (better yet, say MAX_PARALLEL_INVOCATIONS), then you can do something like: char * funny(c) char c; { #define MAX_PARALLEL_INVOCATIONS 8 static char a[MAX_PARALLEL_INVOCATIONS][100]; static int cur = 0; int i; char *ptr; for (i=0 ; i<99 ; i++) a[cur][i] = c; a[cur][99] = '\0'; ptr = &a[cur][0]; if (++cur == MAX_PARALLEL_INVOCATIONS) cur = 0; /* Wrap around to first area. */ return ptr; } This way you have enough static storage for 8 simultaneous ("parallel") results of invoking funny() before results get effectively overwritten. Define the value as large as you like. I wouldn't recommend using this approach for production code (I mean lines of code performing production duties) or anything other than small, tight projects. Use the "temp = funny(...); printf(...,temp,...); free(temp);" solution outlined in another post (where funny doesn't free) for those. The above approach, however, is useful as debug/test code because it doesn't clutter up code with extra temps -- furthermore, the particular example above adds no malloc/free sequences (except via invoking printf, perhaps), which might make a buggy program a bit easier to debug. (Remember, the best debugger in the toughest situations is one that has the smallest impact on its target environment, all else being equal; for that reason, I'd even suggest using fputs(funny(...)); fputs(" ... "); fputs(funny(...)); and so on. Debugging code should try to use the lowest-level stuff possible in case you have to debug at a low level, as in checking for heap corruption and such. But don't torture yourself and your debugging code to fit into this model; if you're doing printfs to show how object states evolve during execution or other such higher-level things, then just make sure you can turn them all of easily via #define if you do run into a low-level bug.) James Craig Burley, Software Craftsperson burley@world.std.com
pl@news.funet.fi.tut.fi (Lehtinen Pertti) (10/02/90)
From article <1990Sep30.163824.12974@ibmpcug.co.uk>, by dylan@ibmpcug.co.uk (Matthew Farwell): > > Forgive me if I'm wrong, but whats wrong with doing .... > > char * > funny(c) > char c; > { > static char a[100]; > int i; > > for (i=0 ; i<99 ; i++) a[i] = c; > a[99] = '\0'; > return (&a[0]); > } > With this function call's like printf( "%s %s\n", funny( 'x' ), funny( 'y' ) ); do not work as expected. --- pl@tut.fi ! All opinions expressed above are Pertti Lehtinen ! purely offending and in subject Tampere University of Technology ! to change without any further Software Systems Laboratory ! notice
mikey@ontek.com (michelle (krill-woman) lee) (10/05/90)
| > char * | > funny(c) | > char c; | > { | > static char a[100]; | > int i; | > | > for (i=0 ; i<99 ; i++) a[i] = c; | > a[99] = '\0'; | > return (&a[0]); | > } | > | | With this function call's like | printf( "%s %s\n", funny( 'x' ), funny( 'y' ) ); | do not work as expected. This sort of thing wouldn't work with malloc/free as originally proposed either. If funny freed the block its return pointer pointed at, the second invocation (not necessarily the one for y, btw) might cause malloc to stomp on the thing that was just freed, before printf even has a chance to print it. It's either that or don't free it and get a memory leak. Better solutions have been mentioned elsewhere in this thread of articles, i.e. using variables in the caller to store the result. the krill, i/o bound