Because you obtain memory, and don't give it back. malloc gets you memory -- to give it back you need free. I probably should have put that in my function but I wasn't sure it would actually work.
Originally Posted by laimaretto
Your first one is perhaps the more insidious, since "return buffer" makes you think that you are lobbing that memory back to the person who called you (which makes it their problem to free it, not yours). However, since you are returning a std::string, that's not true -- the string is constructed from that buffer and the string is returned -- the buffer is no longer needed. In order to deal with this, you should explicitly construct a string object, then free the memory, then return the new string object (don't worry, it has it's own copy of the data, so you giving the original copy away won't hurt).
By using std::[w]string and std::vector, memory management is handled for you.
The second parameter is optional. If a second parameter is not given, then CP_ACP is assumed.
Changing it to "str_to_BSTR()" and "BSTR_to_str()" wouldn't be hard either once you understand what the current code is doing. Or just don't do conversions and work with std::wstring's directly.
BSTR b1, b2;
std::string s = wstr_to_str(b1);
b2 = SysAllocString(str_to_wstr(s).c_str());
Ok, so here are the functions freeing (and deleting) the memory used:
BSTR string2bstr(string input_string)
// MultyBytetoWideChar converts ANSI strings to UNICODE
// int len2 is the required size in wide chars
// it includes the NULL char at the end. So it's "len"+1
// The codepage CP_ACP -AnsiCodePage- is used by Windows (Excel)
// When using 'As string' in VBA causes autmatically UNICODE->ANSI conversion.
int len2 = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, input_string.c_str(),-1, NULL, 0);
// malloc returns a pointer to the begining of the buffer
// buffer size in memory is (len2*sizeof(*buffer))
// 5th parameter of MultiByteToWideChar is LPWSTR
// 1st parameter= CP_ACP = ANSI Code Page
LPWSTR buffer = (LPWSTR)malloc(len2 * sizeof(*buffer));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, input_string.c_str(), -1, buffer,len2);
// SysAllocString allocates a new string and copies the passed string into it.
// The input_parameter must be a Unicode string in 32-bit applications,
// and an ANSI string in 16-bit applications. The input parameter may be NULL.
out_buffer = SysAllocString(buffer);
// since we allocated memory to accomodate the string
// --(LPWSTR)malloc(len2 * sizeof(*buffer)))--
// we must then delete it. To do so, we created BSTR out_buffer and
// copied into it the information within 'buffer'.
string bstr2string(BSTR input_string)
DWORD len, bstrLength;
// +1 for NULL teminator
// bstrLength is measured in Chars
bstrLength = SysStringLen(input_string)+1;
// len is measured in Bytes
len = WideCharToMultiByte(CP_ACP, 0, input_string, bstrLength, 0, 0, 0, 0);
char *buffer = new char[len];
result = WideCharToMultiByte(CP_ACP, 0, input_string, bstrLength,buffer,len, 0, 0);
// since we allocated memory to accomodate the string --new char[len])--
// we must then delete it. To do so, we create std::string out_buffer and
// copy into it the information within 'buffer'.
string out_buffer = buffer;
I'll study your code (I need to deepen my knowledge regarding C++ data types in order to fully understand the difference between std::string and std::wstring before moving on). After that I'll promise I'll try to improve my functions with your suggestions ...
Thanks to everyone ... again, any improvement is very welcome ...
- No error checking on MultiByteToWideChar, WideCharToMultiByte, malloc, SysAllocString, and new (if it doesn't throw).
- Use new/delete in C++ code (malloc/free in C)
- Don't use MB_PRECOMPOSED