Newbie question: Returning LPSTR from a function
Author |
Message |
Kurt #1 / 12
|
 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 |
|
 |
Igor Tandetni #2 / 12
|
 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 |
|
 |
Reginald Blu #3 / 12
|
 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 |
|
 |
Kurt #4 / 12
|
 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 |
|
 |
Kurt #5 / 12
|
 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 |
|
 |
Reginald Blu #6 / 12
|
 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 |
|
 |
Don Grasberge #7 / 12
|
 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 |
|
 |
Doug Harrison [MVP #8 / 12
|
 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 |
|
 |
Reginald Blu #9 / 12
|
 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 |
|
 |
Doug Harrison [MVP #10 / 12
|
 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 |
|
 |
Reginald Blu #11 / 12
|
 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 |
|
 |
Doug Harrison [MVP #12 / 12
|
 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 |
|
|
|