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.
Related
I am trying to make a DLL that exposes a certain API and thus wanted to implement a safe way to copy strings over the DLL boundaries. The DLL implementation is very straight forward - all the functions that return string values take two arguments - char* and size_t&. If the size is big enough I memcpy the contents of the string from within the DLL to the given pointer, set the size to the actual one and return a successful return code. If it is not I set the size to what it should be and return an error code. The DLL side is very straightforward.
Now what is more complicated - how to make a nice template function which given a pointer to some function from the DLL would do all the correct manipulations to fill out an instance of std::string. This is what I came down to:
template<typename I>
CErrorCode GetStringValue(const I& Instance, CErrorCode(I::*pMethod)(char*, size_t&) const, std::string& sValue)
{
std::string sTemporaryValue;
size_t nValueLength = sTemporaryValue.capacity();
sTemporaryValue.resize(nValueLength);
do
{
auto eErrorCode = (Instance.*pMethod)(const_cast<char*>(sTemporaryValue.c_str()), nValueLength);
if (eErrorCode == CErrorCode::BufferTooSmall)
{
sTemporaryValue.resize(nValueLength);
}
else
{
if (eErrorCode == CErrorCode::NoError)
{
sTemporaryValue.resize(nValueLength);
sValue = std::move(sTemporaryValue);
}
return eErrorCode;
}
}
while (true);
}
So I did the initial resize because I can't do that after the first call (since then it would erase the content, since the string is initially empty). But resize fills the string with zero characters, which kind of upsets me (I mean I know I am going to be doing the filling myself anyway). And then I need the resize even after a successful run since if the length was actually smaller I need to resize down. Any suggestions if this can be done I a nicer way?
Since you are using DLLs, my understanding is that you are on Windows, so I'm going to suggest a Windows-specific solution.
Well, the problem of safely passing string across module boundaries has already been solved on Windows by COM memory allocator and BSTR.
So, instead of passing a string pointer and a size pointer, and check if the caller's allocated buffer is large enough, and if not return the required size, etc. it seems much simpler to me to just return BSTRs from the DLL.
BSTRs are allocated using a COM allocator, and so you can allocate them and free them across different module boundaries.
There are also nice C++ wrapper classes around a BSTR, e.g. _bstr_t or ATL's CComBSTR. You can use those at the caller's site.
Once you have a BSTR instance, possibly properly wrapped in a convenient RAII wrapper at the caller's site, you can easily convert it to a std::wstring.
Or, if you want to use the Unicode UTF-8 encoding and std::string, you can convert from the BSTR's native UTF-16 encoding to UTF-8, using WideCharToMultiByte() (this MSDN Magazine article can come in handy).
Bonus reading: Eric’s Complete Guide To BSTR Semantics
P.S.
If you don't want to use the BSTR type, you can still use a common memory allocator provided by COM: e.g. you can allocate your (UTF-8) string memory using CoTaskMemAlloc() in the DLL, and free it using CoTaskMemFree() at the caller's site.
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.
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.
I have a dll that someone made me in C++. I needed to use this dll in VB, in order to do that I had to make another dll in C++ that has functions I can call in VB.
The C++ dll I made has 4 functions. 2 callback functions that retrieve information from the original C++. And 2 functions that I can call from VB to send that information.
I know the original dll works fine as Ive tested it endlessly in a console app.
However when I use it with my dll and VB.. I get random crashes.
There is almost no code in my VB app as its just for testing. It just outputs the information so theres no problem there.
I believe the problem is in the C++ dll I made. I am pretty new with C++.
I think maybe a variable gets accessed in 2spots at the same time (is this possible?) and causes it to crash?
Heres the basic layout of my C++ dll
//global variables
CString allInfo="";
char* info=new char[25000];
//call back function 1
HANDLE OnInfo(SendInfo* tempInfo)
{
CString stringTemp="";
stringTemp=tempInfo->infomessage;
allInfo=allInfo+ stringTemp+"\n";
return 0;
}
//function for vb
BSTR _stdcall vbInfo()
{
allInfo=allInfo.Right(20000); //get last 20,000 characters
strcpy_s(info,20000,allInfo);
BSTR Message;
Message = SysAllocStringByteLen (info, lstrlen(info));
return Message;
}
Crash seems to happen completely randomly.
Any suggestions?
Thanks
Aside from learning that Googling for the CString class reference returns some ahem interesting results, your problem is probably going to be the multiple access of CString.
You didn't post a lot of info, so I'm going to assume the OnInfo method is a callback function that is called by a thread of execution different from the one that calls vbInfo. In this case, you want to look at the CString::operator=() method description on MSDN:
The CString assignment (=) operator reinitializes an existing CString
object with new data. If the destination string (that is, the left
side) is already large enough to store the new data, no new memory
allocation is performed. You should be aware that memory exceptions
may occur whenever you use the assignment operator because new storage
is often allocated to hold the resulting CString object.
Given that there does not appear to be a limit on the size of what you put into the CString, it may be deallocating and allocating the memory in allInfo in one function while you're reading or writing it in another functions. Things don't go so well when you suddenly try to write to unallocated memory.
You might want to look at something like a Critical Section or a mutex to keep both of your functions from hosing the common memory buffer.
You didn't say if your dll is compiled to use Unicode or ANSI strings. You didn't say if the dll that the other person supplied to you is compiled to use Unicode or ANSI strings. The VB caller probably gives you Unicode strings, but it is possible to make the VB caller give you ANSI strings. So we see your code with CString of unknown type, char* pointing to an ANSI string, BSTR pointing to a Unicode string but size allocated in bytes, and who knows what.
There are a lot of articles explaining how to use Unicode, but they'd be a bit too heavy for someone who is pretty new to C++.
It would really be best if you go back to the person who made the other dll for you, and ask that person to add features that you need. Also mention to them that you'll be calling the dll from VB, so you need their dll to handle Unicode strings.
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.