Newbie question: Returning LPSTR from a function 
Author Message
 Newbie question: Returning LPSTR from a function

I have a function that I want to return a LPSTR from the definition looks
something like this:

LPSTR GetDataPath();

And my call something like this:

int main()
{
    LPSTR path = GetDataPath();

Quote:
}

LPSTR GetDataPath()
{
    char buffer[MAX_PATH] = "C:\\Data";
    return &buffer[0];

Quote:
}

The pointer holds in my main routine until I call another routine, and I'm
not using the path variable in that call.
I realize that path is now pointing to something else but how do I make it
work the way I want it to? Any help would be great!

Thanks!
Kurt



Sun, 06 Jul 2003 06:12:18 GMT  
 Newbie question: Returning LPSTR from a function
The path is now pointing to some location on the stack. Any function call,
or allocation of a new local variable, or just comiler deciding it wants to
put a "push" instruction into the code, will overwrite the memory block it
is pointing to.

You can make buffer a static variable:

static char buffer[MAX_PATH] = "C:\\Data";
return buffer;

or just return the string literal

return "C:\\Data";

In both cases you must essentially treat the result as read-only. In the
first case, because if you modify the string, the next call will return
modified string, which is probably not what you would expect. In the second
case, because MSVC puts string literals into a read-only section, so
modifying them will cause an access violation.
--
With best wishes,
    Igor Tandetnik


Quote:
> I have a function that I want to return a LPSTR from the definition looks
> something like this:

> LPSTR GetDataPath();

> And my call something like this:

> int main()
> {
>     LPSTR path = GetDataPath();
> }

> LPSTR GetDataPath()
> {
>     char buffer[MAX_PATH] = "C:\\Data";
>     return &buffer[0];
> }

> The pointer holds in my main routine until I call another routine, and I'm
> not using the path variable in that call.
> I realize that path is now pointing to something else but how do I make it
> work the way I want it to? Any help would be great!

> Thanks!
> Kurt



Sun, 06 Jul 2003 06:29:31 GMT  
 Newbie question: Returning LPSTR from a function
Let me expand on what Igor has said.

This is a common situation and there are several "standard" methods for
retrieving string data from a function:

1.  The static buffer method that Igor suggested.
Advantage:  Quick and simple
Disadvantage:  Not recursive safe nor thread safe (although with TLS it can
be made thread safe.)

2.  Malloc/new:

int main()
{
    LPSTR path = GetDataPath();
    delete [] path;

Quote:
}

LPSTR GetDataPath()
{
    char *buffer = new char [MAX_PATH];
    strcpy(buffer, "C:\\Data");
    return buffer;

Quote:
}

Advantage:  Thread and recursive safe.
Disadvantage:  Prone to memory leaks (forgetting to delete).  Cannot be used
effectively across DLL boundaries (without jumping through hoops.)

3.  Passed in buffer with length:

int main()
{
    char buffer[MAX_PATH];
    LPSTR path = GetDataPath(buffer, MAX_PATH);

Quote:
}

LPSTR GetDataPath(LPSTR buffer, DWORD dwSize)
{
    if (dwSize < sizeof("C:\\Data"))
    {
         buffer = NULL;
    }
    else
    {
        strcpy(buffer, "C:\\Data");
    }
    return buffer;

Quote:
}

Advantage:  Caller is responsible for memory.  Thread and Recursive safe (if
original call is also).
Disadvantage:  Works somewhat poorly with string classes which do not allow
access to their internal buffers (forces a double copy), somewhat harder
interface, can fail if buffer passed in is insufficient.

4. Some form of class object (C++ only)

#include <string>

int main()
{
    std::string path = GetDataPath();

Quote:
}

std::string GetDataPath()
{
    return "C:\\Data";  // built in std::string constructor converts for us
auto-magically

Quote:
}

Advantage:  Very simple to code.  Thread and recursive safe.
Disadvantage:  Requires C++ and a modicum of understanding of the string
class being used.  Cannot be used (effectively) across DLL boundaries.

HTH (and sorry for any coding mistakes, if there are any...I didn't compile
any of this to test.)
--
Reginald Blue                   | Opinions expressed here do not
Natural Language Understanding  | necessarily represent those of
Unisys Corporation              | my employer.
--------------------------------+-------------------------------

NL technology,speech application| My email address is wrong, you
development training, see:      | need to remove the obvious.
http://www.speechdepot.com/     +-------------------------------


Quote:
> I have a function that I want to return a LPSTR from the definition looks
> something like this:

> LPSTR GetDataPath();

> And my call something like this:

> int main()
> {
>     LPSTR path = GetDataPath();
> }

> LPSTR GetDataPath()
> {
>     char buffer[MAX_PATH] = "C:\\Data";
>     return &buffer[0];
> }

> The pointer holds in my main routine until I call another routine, and I'm
> not using the path variable in that call.
> I realize that path is now pointing to something else but how do I make it
> work the way I want it to? Any help would be great!

> Thanks!
> Kurt



Sun, 06 Jul 2003 06:54:32 GMT  
 Newbie question: Returning LPSTR from a function
Thanx!


Quote:
> I have a function that I want to return a LPSTR from the definition looks
> something like this:

> LPSTR GetDataPath();

> And my call something like this:

> int main()
> {
>     LPSTR path = GetDataPath();
> }

> LPSTR GetDataPath()
> {
>     char buffer[MAX_PATH] = "C:\\Data";
>     return &buffer[0];
> }

> The pointer holds in my main routine until I call another routine, and I'm
> not using the path variable in that call.
> I realize that path is now pointing to something else but how do I make it
> work the way I want it to? Any help would be great!

> Thanks!
> Kurt



Sun, 06 Jul 2003 07:09:37 GMT  
 Newbie question: Returning LPSTR from a function
Reginald

How safe is this and will I have memory leaks?

 int main()
 {
     LPSTR path = GetDataPath();
 }

 LPSTR GetDataPath()
 {
     char *buffer = new char [MAX_PATH];

    GetModuleFileName(NULL, &buffer[0], MAX_PATH);
    return strdup(&buffer[0]);
 }

Thanks!
Kurt


Quote:
> Let me expand on what Igor has said.

> This is a common situation and there are several "standard" methods for
> retrieving string data from a function:

> 1.  The static buffer method that Igor suggested.
> Advantage:  Quick and simple
> Disadvantage:  Not recursive safe nor thread safe (although with TLS it
can
> be made thread safe.)

> 2.  Malloc/new:

> int main()
> {
>     LPSTR path = GetDataPath();
>     delete [] path;
> }

> LPSTR GetDataPath()
> {
>     char *buffer = new char [MAX_PATH];
>     strcpy(buffer, "C:\\Data");
>     return buffer;
> }

> Advantage:  Thread and recursive safe.
> Disadvantage:  Prone to memory leaks (forgetting to delete).  Cannot be
used
> effectively across DLL boundaries (without jumping through hoops.)

> 3.  Passed in buffer with length:

> int main()
> {
>     char buffer[MAX_PATH];
>     LPSTR path = GetDataPath(buffer, MAX_PATH);
> }

> LPSTR GetDataPath(LPSTR buffer, DWORD dwSize)
> {
>     if (dwSize < sizeof("C:\\Data"))
>     {
>          buffer = NULL;
>     }
>     else
>     {
>         strcpy(buffer, "C:\\Data");
>     }
>     return buffer;
> }

> Advantage:  Caller is responsible for memory.  Thread and Recursive safe
(if
> original call is also).
> Disadvantage:  Works somewhat poorly with string classes which do not
allow
> access to their internal buffers (forces a double copy), somewhat harder
> interface, can fail if buffer passed in is insufficient.

> 4. Some form of class object (C++ only)

> #include <string>

> int main()
> {
>     std::string path = GetDataPath();
> }

> std::string GetDataPath()
> {
>     return "C:\\Data";  // built in std::string constructor converts for
us
> auto-magically
> }

> Advantage:  Very simple to code.  Thread and recursive safe.
> Disadvantage:  Requires C++ and a modicum of understanding of the string
> class being used.  Cannot be used (effectively) across DLL boundaries.

> HTH (and sorry for any coding mistakes, if there are any...I didn't
compile
> any of this to test.)
> --
> Reginald Blue                   | Opinions expressed here do not
> Natural Language Understanding  | necessarily represent those of
> Unisys Corporation              | my employer.
> --------------------------------+-------------------------------

> NL technology,speech application| My email address is wrong, you
> development training, see:      | need to remove the obvious.
> http://www.speechdepot.com/     +-------------------------------



> > I have a function that I want to return a LPSTR from the definition
looks
> > something like this:

> > LPSTR GetDataPath();

> > And my call something like this:

> > int main()
> > {
> >     LPSTR path = GetDataPath();
> > }

> > LPSTR GetDataPath()
> > {
> >     char buffer[MAX_PATH] = "C:\\Data";
> >     return &buffer[0];
> > }

> > The pointer holds in my main routine until I call another routine, and
I'm
> > not using the path variable in that call.
> > I realize that path is now pointing to something else but how do I make
it
> > work the way I want it to? Any help would be great!

> > Thanks!
> > Kurt



Sun, 06 Jul 2003 07:15:48 GMT  
 Newbie question: Returning LPSTR from a function
"safe" in EXE-only use with two memory leaks.  Unsafe for DLL use.

Change it to:

 int main()
 {
     LPSTR path = GetDataPath();
 }

 LPSTR GetDataPath()
 {
    char buffer[MAX_PATH];
    GetModuleFileName(NULL, buffer, MAX_PATH);
    return strdup(buffer);
 }

will yeild one memory leak and:

 int main()
 {
     LPSTR path = GetDataPath();
     free(path);
 }

 LPSTR GetDataPath()
 {
    char buffer[MAX_PATH];
    GetModuleFileName(NULL, buffer, MAX_PATH);
    return strdup(buffer);
 }

will remove all of them.

(If your "GetDataPath" function is exported from a DLL, you will have
problems because the hidden "malloc" call inside of strdup will allocate
from one heap and a "free" call in an EXE will try to free from another
heap.)

By the way your "&buffer[0]" is generally unnecessary as all arrays in C
(++) decay to pointers.  (Decaying to pointers does not mean they are
pointers...subtle but can be important in the right/wrong circumstance).

--
Reginald Blue                   | Opinions expressed here do not
Natural Language Understanding  | necessarily represent those of
Unisys Corporation              | my employer.
--------------------------------+-------------------------------

NL technology,speech application| My email address is wrong, you
development training, see:      | need to remove the obvious.
http://www.speechdepot.com/     +-------------------------------


Quote:
> Reginald

> How safe is this and will I have memory leaks?

>  int main()
>  {
>      LPSTR path = GetDataPath();
>  }

>  LPSTR GetDataPath()
>  {
>      char *buffer = new char [MAX_PATH];

>     GetModuleFileName(NULL, &buffer[0], MAX_PATH);
>     return strdup(&buffer[0]);
>  }



Sun, 06 Jul 2003 07:45:10 GMT  
 Newbie question: Returning LPSTR from a function
One possible modification to method 2 allows use in DLLs: provide a
recycler function for data allocated by GetDataPath(). Instead of
using the keyword delete, main() would use the function Recycle(),
which because it lives in the same module as GetDataPath() will use
the same heap management.  

It's still prone to memory leaks.

On Tue, 16 Jan 2001 17:54:32 -0500, "Reginald Blue"

Quote:

>Let me expand on what Igor has said.

>This is a common situation and there are several "standard" methods for
>retrieving string data from a function:

>1.  The static buffer method that Igor suggested.
>Advantage:  Quick and simple
>Disadvantage:  Not recursive safe nor thread safe (although with TLS it can
>be made thread safe.)

>2.  Malloc/new:

>int main()
>{
>    LPSTR path = GetDataPath();
>    delete [] path;
>}

>LPSTR GetDataPath()
>{
>    char *buffer = new char [MAX_PATH];
>    strcpy(buffer, "C:\\Data");
>    return buffer;
>}

>Advantage:  Thread and recursive safe.
>Disadvantage:  Prone to memory leaks (forgetting to delete).  Cannot be used
>effectively across DLL boundaries (without jumping through hoops.)

>3.  Passed in buffer with length:

>int main()
>{
>    char buffer[MAX_PATH];
>    LPSTR path = GetDataPath(buffer, MAX_PATH);
>}

>LPSTR GetDataPath(LPSTR buffer, DWORD dwSize)
>{
>    if (dwSize < sizeof("C:\\Data"))
>    {
>         buffer = NULL;
>    }
>    else
>    {
>        strcpy(buffer, "C:\\Data");
>    }
>    return buffer;
>}

>Advantage:  Caller is responsible for memory.  Thread and Recursive safe (if
>original call is also).
>Disadvantage:  Works somewhat poorly with string classes which do not allow
>access to their internal buffers (forces a double copy), somewhat harder
>interface, can fail if buffer passed in is insufficient.

>4. Some form of class object (C++ only)

>#include <string>

>int main()
>{
>    std::string path = GetDataPath();
>}

>std::string GetDataPath()
>{
>    return "C:\\Data";  // built in std::string constructor converts for us
>auto-magically
>}

>Advantage:  Very simple to code.  Thread and recursive safe.
>Disadvantage:  Requires C++ and a modicum of understanding of the string
>class being used.  Cannot be used (effectively) across DLL boundaries.

>HTH (and sorry for any coding mistakes, if there are any...I didn't compile
>any of this to test.)

Don Grasberger

(remove --- from address to e-mail)



Sun, 06 Jul 2003 22:32:58 GMT  
 Newbie question: Returning LPSTR from a function

Quote:

>2.  Malloc/new:

>int main()
>{
>    LPSTR path = GetDataPath();
>    delete [] path;
>}

>LPSTR GetDataPath()
>{
>    char *buffer = new char [MAX_PATH];
>    strcpy(buffer, "C:\\Data");
>    return buffer;
>}

>Advantage:  Thread and recursive safe.
>Disadvantage:  Prone to memory leaks (forgetting to delete).  Cannot be used
>effectively across DLL boundaries (without jumping through hoops.)

I wouldn't exactly describe linking everyone to the same CRT DLL as
jumping through hoops. It's not just the heap; it's file descriptors
and other CRT state as well. IMO, dynamic linking to the CRT should be
SOP, unless you have a very good reason to choose otherwise.

--
Doug Harrison [VC++ MVP]
Eluent Software, LLC
http://www.eluent.com
Tools for Visual C++ and Windows



Mon, 07 Jul 2003 03:27:29 GMT  
 Newbie question: Returning LPSTR from a function
I'm afraid we'll have to agree to disagree then.

Having worked on several C libraries which were customer consumable, I've
learned that you cannot effectively control their environment.  (Oh, you
might want to SAY what they're going to use, but you can't).

Thus, given that you produce a DLL in VC 6.0 which is consumed by a customer
who happens to be using, for example, Borland C++, either you must use one
of the other mechanisms or expose a "Delete" function to clean up from your
own heap.

Thus, "jumping through hoops".

(Of course, in my efforts, luckily I never had to try to hand around file
handles and the like which, you correctly state, would also require a
matched CRT.  I would have to say it would be impossible without matched
CRTs in fact.  The lower level file mechanisms should work though.)

--
Reginald Blue                   | Opinions expressed here do not
Natural Language Understanding  | necessarily represent those of
Unisys Corporation              | my employer.
--------------------------------+-------------------------------

NL technology,speech application| My email address is wrong, you
development training, see:      | need to remove the obvious.
http://www.speechdepot.com/     +-------------------------------



Quote:

> I wouldn't exactly describe linking everyone to the same CRT DLL as
> jumping through hoops. It's not just the heap; it's file descriptors
> and other CRT state as well. IMO, dynamic linking to the CRT should be
> SOP, unless you have a very good reason to choose otherwise.



Mon, 07 Jul 2003 03:56:18 GMT  
 Newbie question: Returning LPSTR from a function

Quote:

>I'm afraid we'll have to agree to disagree then.

>Having worked on several C libraries which were customer consumable, I've
>learned that you cannot effectively control their environment.  (Oh, you
>might want to SAY what they're going to use, but you can't).

>Thus, given that you produce a DLL in VC 6.0 which is consumed by a customer
>who happens to be using, for example, Borland C++, either you must use one
>of the other mechanisms or expose a "Delete" function to clean up from your
>own heap.

That's one of the "good reasons" I was alluding to. A DLL that can be
used in heterogeneous environments like that has to be a black box. It
doesn't even matter that it was written in C++, because it can't be
used as a seamless extension to a C++ program, which shares heap, file
descriptors, etc.

--
Doug Harrison [VC++ MVP]
Eluent Software, LLC
http://www.eluent.com
Tools for Visual C++ and Windows



Mon, 07 Jul 2003 08:13:17 GMT  
 Newbie question: Returning LPSTR from a function
Ah, okay, then we're closer in agreement than I thought.

Personally I ran into this situation far too often which is why I so
strongly recommended avoiding the problem if possible.

To the OP:  To try to sum up, you need to look carefully at what your
project requirements are, ESPECIALLY if it's a DLL and a customer
consumable, to make the right choice between the options presented.

Sound good Doug?

--
Reginald Blue                   | Opinions expressed here do not
Natural Language Understanding  | necessarily represent those of
Unisys Corporation              | my employer.
--------------------------------+-------------------------------

NL technology,speech application| My email address is wrong, you
development training, see:      | need to remove the obvious.
http://www.speechdepot.com/     +-------------------------------



Quote:

> >Having worked on several C libraries which were customer consumable, I've
> >learned that you cannot effectively control their environment.  (Oh, you
> >might want to SAY what they're going to use, but you can't).

> That's one of the "good reasons" I was alluding to. A DLL that can be
> used in heterogeneous environments like that has to be a black box. It
> doesn't even matter that it was written in C++, because it can't be
> used as a seamless extension to a C++ program, which shares heap, file
> descriptors, etc.



Mon, 07 Jul 2003 23:18:30 GMT  
 Newbie question: Returning LPSTR from a function

Quote:

>Ah, okay, then we're closer in agreement than I thought.

>Personally I ran into this situation far too often which is why I so
>strongly recommended avoiding the problem if possible.

>To the OP:  To try to sum up, you need to look carefully at what your
>project requirements are, ESPECIALLY if it's a DLL and a customer
>consumable, to make the right choice between the options presented.

>Sound good Doug?

Yes, thanks!

--
Doug Harrison [VC++ MVP]
Eluent Software, LLC
http://www.eluent.com
Tools for Visual C++ and Windows



Wed, 09 Jul 2003 03:52:38 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. Newbie question: Returning LPSTR from a function

2. newbie question: returning structs from functions

3. Question about signal()/pointers to functions that return pointers to functions

4. QUESTION: functions returning pointers to functions

5. a question on function returning a pointer to a function

6. Pointer to function returning pointer to function returning...

7. newbie q (difference from LPCH and LPSTR

8. Newbie: DWORD to LPSTR

9. Newbie: Want function to return boolean value

10. Functions that return arrays (newbie)

11. Newbie, help creating a function that returns two strings

12. Newbie, help with function that returns two strings

 

 
Powered by phpBB® Forum Software