I'm finalizing my function for safe string retrieval and decided to turn my compiler warnings up to see if any of my code raised any flags.
Currently I am receiving the following compiler warnings on Pelles C IDE:
stringhandle.c(39): warning #2800: Potentially dangling object 'str' used after call to function 'realloc'.
stringhandle.c(50): warning #2800: Potentially dangling object 'str' used after call to function 'realloc'.
Here is my function (read below if you would rather read the question in it's entirety before reading code):
char *getstr(void)
{
char *str, *tmp;
int bff = STRBFF, ch = -1, pt = 0;
if(!(str = malloc(bff)))
{
printf("\nError! Memory allocation failed!");
return 0x00;
}
while(ch)
{
ch = getc(stdin);
if (ch == EOF || ch == '\n' || ch == '\r') ch = 0;
if (bff <= pt)
{
bff += STRBFF;
if(!(tmp = realloc(str, bff)))
{
free(str); //line 39 triggers first warning
str = 0x00;
printf("\nError! Memory allocation failed!");
return 0x00;
}
str = tmp;
}
str[pt++] = (char)ch;
}
str[pt] = 0x00;
if(!(tmp = realloc(str, pt)))
{
free(str); //line 50 triggers second warning
str = 0x00;
printf("\nError! Memory allocation failed!");
return 0x00;
}
str = tmp;
return str;
}
I think understand why I am being warned that str
may be dangling. I am freeing the allocated space pointed to by str
if an error occurs, however my function has no further calls to str
after it being freed. As a fix, I just tried doing free(str)
followed by str = 0x00
. Shouldn't that make the pointer str
no longer dangling? Does it have something to do with my tmp
pointer? I don't free or set tmp
to 0x00
either, since it should already be 0x00
if realloc
fails. But should I be setting it to 0x00
on success, since it is still technically pointing exactly where str
is and is no longer needed?
In short:
str
may be dangling?tmp
pointer correctly?Just to illustrate my points:
#include <stdio.h>
#include <stdlib.h>
static inline void * myrealloc(void *org, size_t newsize)
{
char * new;
new = realloc(org, newsize);
if (!new) {
fprintf(stderr, "\nError! Memory allocation failed!\n");
free (org);
return NULL;
}
return new;
}
char *getstr(void)
{
#define STRBFF 256
char *str = NULL;
size_t size , used ;
for (size=used=0; ; ) {
int ch;
if (used >=size) {
str = myrealloc(str, size += STRBFF);
if(!str) return NULL;
}
ch = getc(stdin);
if (ch == EOF || ch == '\n' || ch == '\r') ch = 0;
str[used++] = ch;
if (!ch) break;
}
str = myrealloc(str, used);
return str;
}
Now, if your compiler supports inlining, the calls to myrealloc() will be replaced by the equivalent of your original code, and the actual myrealloc()function will virtually disappear. (check the disassembled output).