When I create a function that returns a char* or const char*, is it assumed that the calling function must deallocate the returned value when it is finished with it? Otherwise, how would it get deallocated? I'm looking some other code which calls a function that returns a char* and there is not a delete statement in the calling function. Example:
char* foo();
void bar()
{
char* result = foo();
//I should have "delete result" here right?
}
EDIT:
So In my application here is foo:
LPTSTR GetTempPath(LPCTSTR fileName)
{
LPTSTR tempPath = new TCHAR[500];
GetTempPath(500,tempPath);
printf("Temp Path %ls\n",tempPath);
PathAppend(tempPath, fileName);
_tprintf(_T("New temp path: %s\n"), tempPath);
return tempPath;
}
I wasn't sure how to write this without the new TCHAR.
I'm assuming this has to be deleted? Is there a better way to write it?
If you're using C++ and not C, you should use std::string to get rid of the problem.
There are (at least) two common conventions when a char* is returned by a function. You cannot tell which is in force without reading the documentation of the function.
The function returns a pointer to statically allocated memory. In which case the caller does not need to deallocate it.
The function returns a pointer to heap allocated memory. In which case the caller does need to deallocate it. The documentation for the function must specify how the caller must deallocate the function (free, delete etc.)
Now, since you are in charge of writing your own functions, you can choose whatever protocol you like. And in your case you should not return a char* from your functions. Choose a third way. Return a std::string and let the standard library take care of allocation and deallocation. Do it this way to make life easier for the consumer of the library.
In fact, since you are writing C++, you should be shunning char*. Sure you have to use C string when interacting with the Windows API. But leave it at that. Don't pass the pain on to the consumer of your library. Hide that complexity away.
In your situation I would make sure that you have a function that can combine two std::string instances. This could perhaps be implemented using PathAppend, but it's easy enough to roll your own. Then the only interaction you need with the Windows API is a function that returns the temporary directory in a string. That looks like this:
string GetTempDir()
{
char buff[MAX_PATH+1];
DWORD count = GetTempPath(MAX_PATH+1, buff); // I've omitted error checking
return string(buff, count);
}
The code in this function is the only code that needs to deal with C strings. You can now forget all about them in the rest of your code which can treat this as a black box. Don't let the implementation details of the lowest common denominator C interface of Win32 leak into your nicely factored C++ code.
If foo() is in an external dynamic library, the library should provide some explicit way to delete result,if delete is required, or some other way to close the working session and so on.
To answer the question you posed ("is it assumed that the calling function must deallocate the returned value when it is finished with it? Otherwise, how would it get deallocated?"):
No, the caller does not necessarily have to deallocate the string. Looking at man ctime:
char *ctime(const time_t *timep);
The return value points to a statically allocated string which might be overwritten by subsequent calls to any of the date and time functions.
Which means you do not delete nor free the string it returns.
Related
I have a C++ API function that is called by Install Shield via InstallScript:
SQLHELPER_API LPCSTR GetAvailableAppName(LPCSTR appNameP)
{
//return "this works just fine";
std::string newAppName = "I work, maybe?";
LPCSTR returnVal = newAppName.c_str();
return returnVal;
}
The only thing that returns is an empty string. If I just return passed in variable "appNameP" it returns that just fine as well.
My main issue is that I need to pass in a LPCSTR and perform some string operation on it.
A LPCSTR is the same as const char *.
Passing a C-style string like that to a function call is fine.
Returning a pointer to a local function variable is not fine, because this local variable doesn´t exist anymore after the function ends. As soon as you´re using the pointer in main (or whereever the function was called), it points to a memory which doesn´t belong to you anymore, and the value may have changed already.
There are several possibilites, each with a downside:
Using only memory you got as parameter (eg. appNameP, because this has to be something from outside and will still exist after the function ends). Downside: You need to pass something fitting for that purpose => the function signature or at least the requirements for the parameters changes, and you´ve to check/change how it is called.
Allocating something with new. Downside: Somewhere later, outside, delete[] have to be called.
Returning something like std::string. Downside: As in #1, the function signature changes, and you´ve to change how it is called.
If InstallShield calls this function itself:
What InstallShield expects you to do should be somewhere in the documentation.
Let me start off by saying it's been several years (over 8) since I have had to mess with C++. I am very rusty again and it looks like I'll have to start doing some side projects to get the hang of it.
I know this is really simple and I'm sure it's something very small that I am doing incorrectly... I am receiving garbage characters from my returned value and I can't figure out why. Maybe it has to do with my encoding? Not sure.
A simple function to retrieve the value from an INI file in Windows:
LPCTSTR getConfigValue(LPCTSTR key) {
char retval[256];
DWORD dw;
if ((dw = GetPrivateProfileStringA("RLWELF", "DestinationIP", NULL, retval, 256, ".\\rlwelf.ini")) > 0) {
return NULL;
}
OutputDebugStringA(retval);
return (LPCTSTR)retval;
}
Thank you in advance!
return (LPCTSTR)retval;
You are returning the address of a local variable. That local variable is destroyed as soon as the function returns. It is therefore undefined behaviour for the caller to de-reference the returned pointer. You would need to:
Have the caller provide a buffer into which the function can write.
Have the function allocate memory on the heap. The caller would need to deallocate it.
Start using the C++ standard library and return a std::string.
Option 3 is head and shoulders above the others.
Beyond that the cast is dubious. I suspect that you are compiling with UNICODE defined. Which means that LPCTSTR expands to const wchar_t*. That in turn means that your cast would erroneous. You would be lying to the compiler. The compiler will always exact its revenge when you lie to it.
You should get out of the habit of using TCHAR. Compile with UNICODE defined and use the platform native UTF-16 character encoding for text.
Finally, GetPrivateProfileString is a really ancient API that is not encouraged to be used nowadays. The documentation says:
This function is provided only for compatibility with 16-bit Windows-based applications.
If you must use INI files, then use a good C++ library. This will result in a code writing experience that is many orders of magnitude cleaner, safer and quicker.
retval is a local variable, it is destroyed at the end of the function, so when you try to return it, the caller receives a pointer to garbage.
Instead, you could malloc a buffer and return it, take an output pointer in argument, or return a unique_ptr to a buffer.
In our C++ code, we have our own string class (for legacy reasons). It supports a method c_str() much like std::string. What I noticed is that many developers are using it incorrectly. I have reduced the problem to the following line:
const char* x = std::string("abc").c_str();
This seemingly innocent code is quite dangerous in the sense that the destructor on std::string gets invoked immediately after the call to c_str(). As a result, you are holding a pointer to a de-allocated memory location.
Here is another example:
std::string x("abc");
const char* y = x.substr(0,1).c_str();
Here too, we are using a pointer to de-allocated location.
These problems are not easy to find during testing as the memory location still contains valid data (although the memory location itself is invalid).
I am wondering if you have any suggestions on how I can modify class/method definition such that developers can never make such a mistake.
The modern part of the code should not deal with raw pointers like that.
Call c_str only when providing an argument to a legacy function that takes const char*. Like:
legacy_print(x.substr(0,1).c_str())
Why would you want to create a local variable of type const char*? Even if you write a copying version c_str_copy() you will just get more headache because now the client code is responsible for deleting the resulting pointer.
And if you need to keep the data around for a longer time (e.g. because you want to pass the data to multiple legacy functions) then just keep the data wrapped in a string instance the whole time.
For the basic case, you can add a ref qualifier on the "this" object, to make sure that .c_str() is never immediately called on a temporary. Of course, this can't stop them from storing in a variable that leaves scope before the pointer does.
const char *c_str() & { return ...; }
But the bigger-picture solution is to replace all functions from taking a "const char *" in your codebase with functions that take one of your string classes (at the very least, you need two: an owning string and a borrowed slice) - and make sure that none of your string class does cannot be implicitly constructed from a "const char *".
The simplest solution would be to change your destructor to write a null at the beginning of the string at destruction time. (Alternatively, fill the entire string with an error message or 0's; you can have a flag to disable this for release code.)
While it doesn't directly prevent programmers from making the mistake of using invalid pointers, it will definitely draw attention to the problem when the code doesn't do what it should do. This should help you flush out the problem in your code.
(As you mentioned, at the moment the errors go unnoticed because for the most part the code will happily run with the invalid memory.)
Consider using Valgrind or Electric Fence to test your code. Either of these tools should trivially and immediately find these errors.
I am not sure that there is much you can do about people using your library incorrectly if you warn them about it. Consider the actual stl string library. If i do this:
const char * lala = std::string("lala").c_str();
std::cout << lala << std::endl;
const char * lala2 = std::string("lalb").c_str();
std::cout << lala << std::endl;
std::cout << lala2 << std::endl;
I am basically creating undefined behavior. In the case where i run it on ideone.com i get the following output:
lala
lalb
lalb
So clearly the memory of the original lala has been overwritten. I would just make it very clear to the user in the documentation that this sort of coding is bad practice.
You could remove the c_str() function and instead provide a function that accepts a reference to an already created empty smart pointer that resets the value of the smart pointer to a new copy of the string. This would force the user to create a non temporary object which they could then use to get the raw c string and it would be destructed and free the memory when exiting the method scope.
This assumes though that your library and its users would be sharing the same heap.
EDIT
Even better, create your own smart pointer class for this purpose whose destructor calls a library function in your library to free the memory so it can be used across DLL boundaries.
Note: when I say "static string" here I mean memory that can not be handled by realloc.
Hi, I have written a procedure that takes a char * argument and I would like to create a duplicate IF the memory is not relocatable/resizable via realloc. As is, the procedure is a 'heavy' string processor, so being ignorant and duplicating the string whether or not it is static will surely cause some memory overhead/processing issues in the future.
I have tried to use exception handlers to modify a static string, the application just exits without any notice. I step back, look at C and say: "I'm not impressed." That would be an exception if I have ever heard of one.
I tried to use exception handlers to call realloc on a static variable... Glib reports that it can't find some private information to a structure (I'm sure) I don't know about and obviously calls abort on the program which means its not an exception that can be caught with longjmp/setjmp OR C++ try, catch finally.
I'm pretty sure there must be a way to do this reasonably. For instance dynamic memory most likely is not located anywhere near the static memory so if there is a way to divulge this information from the address... we might just have a bingo..
I'm not sure if there are any macros in the C/C++ Preprocessors that can identify the source and type of a macro argument, but it would be pretty dumb if it didn't. Macro Assemblers are pretty smart about things like that. Judging by the lack of robust error handling, I would not be a bit surprised if it did not.
C does not provide a portable way to tell statically allocated memory blocks from dynamically allocated ones. You can build your own struct with a string pointer and a flag indicating the type of memory occupied by the object. In C++ you can make it a class with two different constructors, one per memory type, to make your life easier.
As far as aborting your program goes, trying to free or re-allocate memory that has not been allocated dynamically is undefined behavior, so aborting is a fair game.
You may be able to detect ranges of memory and do some pointer comparisons. I've done this in some garbage collection code, where I need to know whether a pointer is in the stack, heap, or elsewhere.
If you control all allocation, you can simply keep min and max bounds based on every dynamic pointer that ever came out of malloc, calloc or realloc. A pointer lower than min or greater than max is probably not in the heap, and this min and max delimited region is unlikely to intersect with any static area, ever. If you know that a pointer is either static or it came from malloc, and that pointer is outside of the "bounding box" of malloced storage, then it must be static.
There are some "museum" machines where that sort of stuff doesn't work and the C standard doesn't give a meaning to comparisons of pointers to different objects using the relational operators, other than exact equality or inequality.
Any solution you would get would be platform specific, so you might want to specify the platform you are running on.
As for why a library should call abort when you pass it unexpected parameters, that tends to be safer than continuing execution. It's more annoying, certainly, but at that point the library knows that the code calling into it is in an state that cannot be recovered from.
I have written a procedure that takes a char * argument and I would like to create a duplicate IF the memory is not relocatable/resizable via realloc.
Fundamentally, the problem is that you want to do memory management based on information that isn't available in the scope you're operating in. Obviously you know if the string is on the stack or heap when you create it, but that information is lost by the time you're inside your function. Trying to fix that is going to be nearly impossible and definitely outside of the Standard.
I have tried to use exception handlers to modify a static string, the application just exits without any notice. I step back, look at C and say: "I'm not impressed." That would be an exception if I have ever heard of one.
As already mentioned, C doesn't have exceptions. C++ could do this, but the C++ Standards Committee believes that having C functions behave differently in C++ would be a nightmare.
I'm pretty sure there must be a way to do this reasonably.
You could have your application replace the default stack with one you created (and, as such, know the range of addresses in) using ucontext.h or Windows Fibers, and check if the address is inside the that range. However, (1) this puts a huge burden on any application using your library (of course, if you wrote the only application using your library, then you may be willing to accept that burden); and (2) doesn't detect memory that can't be realloced for other reasons (allocated using static, allocated using a custom allocator, allocated using SysAlloc or HeapAlloc on Windows, allocated using new in C++, etc.).
Instead, I would recommend having your function take a function pointer that would point at a function used to reallocate the memory. If the function pointer is NULL, then you duplicate the memory. Otherwise, you call the function.
original poster here. I neglected to mention that I have a working solution to the problem, it is not as robust as I would have hoped for. Please do not be upset, I appreciate everyone participating in this Request For Comments and Answers. The 'procedure' in question is variadic in nature and expects no more than 63 anonymous char * arguments.
What it is: a multiple string concatenator. It can handle many arguments but I advise the developer against passing more than 20 or so. The developer never calls the procedure directly. Instead a macro known as 'the procedure name' passes the arguments along with a trailing null pointer, so I know when I have met the end of statistics gathering.
If the function recieves only two arguments, I create a copy of the first argument and return that pointer. This is the string literal case. But really all it is doing is masking strdup
Failing the single valid argument test, we proceed to realloc and memcpy, using record info from a static database of 64 records containing each pointer and its strlen, each time adding the size of the memcopy to a secondary pointer (memcpy destination) that began as a copy of the return value from realloc.
I've written a second macro with an appendage of 'd' to indicate that the first argument is not dynamic, therefore a dynamic argument is required, and that macro uses the following code to inject a dynamic argument into the actual procedure call as the first argument:
strdup("")
It is a valid memory block that can be reallocated. Its strlen returns 0 so when the loop adds the size of it to the records, it affects nothing. The null terminator will be overwritten by memcpy. It works pretty damned well I should say. However being new to C in only the past few weeks, I didn't understand that you can't 'fool proof' this stuff. People follow directions or wind up in DLL hell I suppose.
The code works great without all of these extra shenanigans do-hickies and whistles, but without a way to reciprocate a single block of memory, the procedure is lost on loop processing, because of all the dynamic pointer mgmt. involved. Therefore the first argument must always be dynamic. I read somehwere someone had suggested using a c-static variable holding the pointer in the function, but then you can't use the procedure to do other things in other functions, such as would be needed in a recursive descent parser that decided to compile strings as it went along.
If you would like to see the code just ask!
Happy Coding!
mkstr.cpp
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
struct mkstr_record {
size_t size;
void *location;
};
// use the mkstr macro (in mkstr.h) to call this procedure.
// The first argument to mkstr MUST BE dynamically allocated. i.e.: by malloc(),
// or strdup(), unless that argument is the sole argument to mkstr. Calling mkstr()
// with a single argument is functionally equivalent to calling strdup() on the same
// address.
char *mkstr_(char *source, ...) {
va_list args;
size_t length = 0, item = 0;
mkstr_record list[64]; /*
maximum of 64 input vectors. this goes beyond reason!
the result of this procedure is a string that CAN be
concatenated by THIS procedure, or further more reallocated!
We could probably count the arguments and initialize properly,
but this function shouldn't be used to concatenate more than 20
vectors per call. Unless you are just "asking for it".
In any case, develop a workaround. Thank yourself later.
*/// Argument Range Will Not Be Validated. Caller Beware!!!
va_start(args, source);
char *thisArg = source;
while (thisArg) {
// don't validate list bounds here.
// an if statement here is too costly for
// for the meager benefit it can provide.
length += list[item].size = strlen(thisArg);
list[item].location = thisArg;
thisArg = va_arg(args, char *);
item++;
}
va_end(args);
if (item == 1) return strdup(source); // single argument: fail-safe
length++; // final zero terminator index.
char *str = (char *) realloc(source, length);
if (!str) return str; // don't care. memory error. check your work.
thisArg = (str + list[0].size);
size_t count = item;
for (item = 1; item < count; item++) {
memcpy(thisArg, list[item].location, list[item].size);
thisArg += list[item].size;
}
*(thisArg) = '\0'; // terminate the string.
return str;
}
mkstr.h
#ifndef MKSTR_H_
#define MKSTR_H_
extern char *mkstr_(char *string, ...);
// This macro ensures that the final argument to "mkstr" is null.
// arguments: const char *, ...
// limitation: 63 variable arguments max.
// stipulation: caller must free returned pointer.
#define mkstr(str, args...) mkstr_(str, ##args, NULL)
#define mkstrd(str, args...) mkstr_(strdup(str), ##args, NULL)
/* calling mkstr with more than 64 arguments should produce a segmentation fault
* this is not a bug. it is intentional operation. The price of saving an in loop
* error check comes at the cost of writing code that looks good and works great.
*
* If you need a babysitter, find a new function [period]
*/
#endif /* MKSTR_H_ */
Don't for get to mention me in the credits. She's fine and dandy.
We are using the CString class throughout most of our code. However sometimes we need to convert to a char *. at the moment we have been doing this using variable.GetBuffer(0) and this seems to work ( this mainly happens when passing the Csting into a function where the function requires a char *). The function accepts this and we keep going.
However we have lately become worried about how this works, and whether there is a better way to do it.
The way i understand it to work is it passes a char pointer into the function that points at the first character in the CString and all works well.
I Guess we are just worried about memory leaks or any unforseen circumstances where this might not be a good idea.
If your functions only require reading the string and not modifying it, change them to accept const char * instead of char *. The CString will automatically convert for you, this is how most of the MFC functions work and it's really handy. (Actually MFC uses LPCTSTR, which is a synonym for const TCHAR * - works for both MBC and Unicode builds).
If you need to modify the string, GetBuffer(0) is very dangerous - it won't necessarily allocate enough memory for the resulting string, and you could get some buffer overrun errors.
As has been mentioned by others, you need to use ReleaseBuffer after GetBuffer. You don't need to do that for the conversion to const char *.
# the OP:
>>> I Guess we are just worried about memory leaks or any ...
Hi, calling the GetBuffer method won't lead to any memory leaks. Because the destructor is going to deallocate the buffer anyway. However, others have already warned you about the potential issues with calling this method.
#Can >>> when you call the getbuffer function it allocates memory for you.
This statement is not completely true. GetBuffer(0) does NOT allocate any memory. It merely returns a pointer to the internal string buffer that can be used to manipulate the string directly from "outside" the CString class.
However, if you pass a number, say N to it like GetBuffer(N), and if N is larger than the current length of the buffer, then the function ensures that the returned buffer is at least as large as N by allocating more memory.
Cheers,
Rajesh.
MVP, Visual ++.
when you call the getbuffer function it allocates memory for you.
when you have done with it, you need to call releasebuffer to deallocate it
try the documentation at http://msdn.microsoft.com/en-us/library/awkwbzyc.aspx for help on that.