www.digitalmars.com Home | Search | C & C++ | D | DMDScript | News Groups | index | prev | next
Archives

D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger

C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows

digitalmars.empire
digitalmars.DMDScript

c++ - Warning 15: returning address of automatic 'identifier'

↑ ↓ ← DeadlyWarning <DeadlyWarning_member pathlink.com> writes:
Warning 15: returning address of automatic 'identifier' 

Warning. This results in an invalid pointer beyond the end of the stack. When
the function returns, the caller receives an illegal address that can cause a
general protection fault. 

How is this caused and how is it fixed, I've never ran into this before, but it
pops up now and again in my programs, ruining the functions I write.

Here is a function in which it appears(There are a few non-local variables):

LPSTR GetField(LPSTR id, int record)
{
int alphaix, betaix = 0, offset, count;
char return_string[2000];
ZeroMemory(return_string, 2000);
for (alphaix = 0;alphaix < num_headers;alphaix++)
{
if (strnicmp((header_id + (alphaix * 11)), id, strlen(id)) == 0)
break;
betaix += (header_length[alphaix]);
}
if (alphaix == num_headers)
return "ERR1";
offset = (record_bytes * record) + header_bytes + betaix + 1;
SetFilePointer(scanfile, offset, NULL, FILE_BEGIN);
wfgets(return_string, header_length[alphaix] + 1, scanfile);
// Causes warning 15
return return_string;
}
Sep 30 2002
"Walter" <walter digitalmars.com> writes:
Try returning strdup(return_string), that should take care of the problem.

"DeadlyWarning" <DeadlyWarning_member pathlink.com> wrote in message
news:ana6aa$1pue$1 digitaldaemon.com...
 Warning 15: returning address of automatic 'identifier'

 Warning. This results in an invalid pointer beyond the end of the stack.

 the function returns, the caller receives an illegal address that can

 general protection fault.

 How is this caused and how is it fixed, I've never ran into this before,

 pops up now and again in my programs, ruining the functions I write.

 Here is a function in which it appears(There are a few non-local

 LPSTR GetField(LPSTR id, int record)
 {
 int alphaix, betaix = 0, offset, count;
 char return_string[2000];
 ZeroMemory(return_string, 2000);
 for (alphaix = 0;alphaix < num_headers;alphaix++)
 {
 if (strnicmp((header_id + (alphaix * 11)), id, strlen(id)) == 0)
 break;
 betaix += (header_length[alphaix]);
 }
 if (alphaix == num_headers)
 return "ERR1";
 offset = (record_bytes * record) + header_bytes + betaix + 1;
 SetFilePointer(scanfile, offset, NULL, FILE_BEGIN);
 wfgets(return_string, header_length[alphaix] + 1, scanfile);
 // Causes warning 15
 return return_string;
 }

Sep 30 2002
↑ ↓ Heinz Saathoff <hsaat bre.ipnet.de> writes:
Walter schrieb...
 
 Try returning strdup(return_string), that should take care of the problem.

But then the caller has to free the allocated memory to prevent memory leaks. - Heinz
Sep 30 2002
↑ ↓ → "Walter" <walter digitalmars.com> writes:
"Heinz Saathoff" <hsaat bre.ipnet.de> wrote in message
news:MPG.180365b21bde22f49896b1 news.digitalmars.com...
 Walter schrieb...
 Try returning strdup(return_string), that should take care of the


 But then the caller has to free the allocated memory to prevent memory
 leaks.

Yes, you're right.
Oct 01 2002
→ Laurentiu Pancescu <plaur crosswinds.net> writes:
The problem with your code can be resumed to:

char *buggy(void)
{
   char str[1000];
   return str;
}

The "str" array is created on stack when entering the function, and 
destroyed when exiting the function.  The caller of the function 
receives a pointer to memory that no longer exists!  In fact, it still 
exists, but it may contain anything by the time you try to read it. 
And, if you write there, it could be even worse (crash, probably).

You could fix this in several ways:

- return strdup(return_string), as Walter suggested, but make sure you 
call free() on the returned pointer after you don't need it anymore - 
otherwise your program will leak memory!

- use a static array, which gets you out of trouble when you need large 
arrays.  This has the disadvantage that your function becomes not 
reentrant (advantage would be that a buffer overflow cannot start 
executing random code - security might or might not be an issue for you)

- only if you're programming in C++: use a std::string (DMC doesn't 
support namespaces yet, AFAIK, so try just with string), in which case 
the C++ standard library will handle memory management.  This is by far 
the best solution IMHO.

Regards,
   Laurentiu


DeadlyWarning wrote:
 Warning 15: returning address of automatic 'identifier' 
 
 Warning. This results in an invalid pointer beyond the end of the stack. When
 the function returns, the caller receives an illegal address that can cause a
 general protection fault. 
 
 How is this caused and how is it fixed, I've never ran into this before, but it
 pops up now and again in my programs, ruining the functions I write.
 
 Here is a function in which it appears(There are a few non-local variables):
 
 LPSTR GetField(LPSTR id, int record)
 {
 int alphaix, betaix = 0, offset, count;
 char return_string[2000];
 ZeroMemory(return_string, 2000);
 for (alphaix = 0;alphaix < num_headers;alphaix++)
 {
 if (strnicmp((header_id + (alphaix * 11)), id, strlen(id)) == 0)
 break;
 betaix += (header_length[alphaix]);
 }
 if (alphaix == num_headers)
 return "ERR1";
 offset = (record_bytes * record) + header_bytes + betaix + 1;
 SetFilePointer(scanfile, offset, NULL, FILE_BEGIN);
 wfgets(return_string, header_length[alphaix] + 1, scanfile);
 // Causes warning 15
 return return_string;
 }
 
 

Sep 30 2002
→ Larry Brasfield <larry_brasfield snotmail.com> writes:
I'm just expanding upon Walter's answer so that
you will understand what the warning means and
why you should revise code that induces it.

In article <ana6aa$1pue$1 digitaldaemon.com>, 
DeadlyWarning (DeadlyWarning_member pathlink.com) says...
 Warning 15: returning address of automatic 'identifier' 

The warning could be more accurately phrased: "Returning address of object that does not exist after the return."
 Warning. This results in an invalid pointer beyond the end of the stack. When
 the function returns, the caller receives an illegal address that can cause a
 general protection fault. 

This is one possible outcome. The behavior is not defined. It is also possible that the object whose address was returned will become corrupted by the time its address is used.
 How is this caused and how is it fixed, I've never ran into this before, but it
 pops up now and again in my programs, ruining the functions I write.

No, the functions that induce that warning were ruined before the compiler saw them. You fix this problem in one of several ways: Create a separately allocated object, whose lifetime extend until it is freed, and return a pointer to it (Walter's strdup() suggestion); pass a pointer into the function which addresses an object that will exist after function return and modify that object in your function; make your function return a C++ std::string object. (a variation on separate allocation)
 Here is a function in which it appears(There are a few non-local variables):
 
 LPSTR GetField(LPSTR id, int record)
 {
 int alphaix, betaix = 0, offset, count;
 char return_string[2000];

The above 5 identifiers refer to 'auto' objects whose lifetime extends from entry of the block to exit from the block. It makes no sense to refer to those objects at any time beyond that lifetime, hence the warning when you return one of their addresses. Upon executing the return, the block is exited and the objects no longer exist in any reliable or defined manner.
 ZeroMemory(return_string, 2000);
 for (alphaix = 0;alphaix < num_headers;alphaix++)
 {
 if (strnicmp((header_id + (alphaix * 11)), id, strlen(id)) == 0)
 break;
 betaix += (header_length[alphaix]);
 }
 if (alphaix == num_headers)
 return "ERR1";
 offset = (record_bytes * record) + header_bytes + betaix + 1;
 SetFilePointer(scanfile, offset, NULL, FILE_BEGIN);
 wfgets(return_string, header_length[alphaix] + 1, scanfile);
 // Causes warning 15

Consider that warning a favor.
 return return_string;
 }

-- -Larry Brasfield (address munged, s/sn/h/ to reply)
Sep 30 2002