VC++: how-to convert CString to TCHAR* - visual-c++

VC++: how-to convert CString value to TCHAR*.One method is GetBuffer(..) function. Is there any other way we can convert CString to TCHAR*.

CString::GetBuffer() doesn't make any conversion, it gives direct access to string.
To make a copy of CString:
TCHAR* buf = _tcsdup(str);
free(buf);
or
TCHAR* buf = new TCHAR[str.GetLength() + 1];
_tcscpy_s(buf, str.GetLength() + 1, str);
delete[]buf;
However the above code is usually not useful. You might want to modify it like so:
TCHAR buf[300];
_tcscpy_s(buf, TEXT("text"));
Usually you need to this to read data in to buffer, so you want to make the buffer size larger than the current size.
Or you can just use CString::GetBuffer(), again you might want to make the buffer size bigger.
GetWindowText(hwnd, str.GetBuffer(300), 300);
str.ReleaseBuffer(); //release immediately
TRACE(TEXT("%s\n"), str);
In other cases you need only const cast const TCHAR* cstr = str;
Lastly, TCHAR is not very useful. If your code is compatible with both ANSI and unicode then you might as well make it unicode only. But that's just a suggestion.

This depends on why you need a non-const TCHAR*. There are two main scenarios:
Manual update of the contents of a CString object:In that case you will have to call CSimpleStringT::GetBuffer (specifying the minimal length of the final string), update the contents, and call CSimpleStringT::ReleaseBuffer. Calling ReleaseBuffer is mandatory, as it updates internal state. Failure to call ReleaseBuffer can lead to the string exposing unexpected behavior.
Failure to expose const-correctness at an interface:If this is the case you can either update the interface to take a const TCHAR* instead of a TCHAR*, and invoke CSimpleStringT::operator PCXSTR by passing the CString object.If you cannot update the interface, you are best advised to make a copy into a TCHAR array and pass a pointer to this copy.If you can make sure that the implementation will not ever modify the contents referenced through the TCHAR* parameter, you could use a const_cast instead. This is not recommended, as it can introduce bugs in the future, by modifying unrelated code.

Related

Code analysis C26408 — Replacing the m_pszHelpFilePath variable in InitInstance

In my application's InitInstance function, I have the following code to rewrite the location of the CHM Help Documentation:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free((void*)m_pszHelpFilePath);
m_pszHelpFilePath = _tcsdup(strHelp);
It is all functional but it gives me a code analysis warning:
C26408 Avoid malloc() and free(), prefer the nothrow version of new with delete (r.10).
When you look at the official documentation for m_pszHelpFilePath it does state:
If you assign a value to m_pszHelpFilePath, it must be dynamically allocated on the heap. The CWinApp destructor calls free( ) with this pointer. You many want to use the _tcsdup( ) run-time library function to do the allocating. Also, free the memory associated with the current pointer before assigning a new value.
Is it possible to rewrite this code to avoid the code analysis warning, or must I add a __pragma?
You could (should?) use a smart pointer to wrap your reallocated m_pszHelpFilePath buffer. However, although this is not trivial, it can be accomplished without too much trouble.
First, declare an appropriate std::unique_ptr member in your derived application class:
class MyApp : public CWinApp // Presumably
{
// Add this member...
public:
std::unique_ptr<TCHAR[]> spHelpPath;
// ...
};
Then, you will need to modify the code that constructs and assigns the help path as follows (I've changed your C-style cast to an arguably better C++ cast):
// First three (almost) lines as before ...
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free(const_cast<TCHAR *>(m_pszHelpFilePath));
// Next, allocate the shared pointer data and copy the string...
size_t strSize = static_cast<size_t>(strHelp.GetLength() + 1);
spHelpPath std::make_unique<TCHAR[]>(strSize);
_tcscpy_s(spHelpPath.get(), strHelp.GetString()); // Use the "_s" 'safe' version!
// Now, we can use the embedded raw pointer for m_pszHelpFilePath ...
m_pszHelpFilePath = spHelpPath.get();
So far, so good. The data allocated in the smart pointer will be automatically freed when your application object is destroyed, and the code analysis warnings should disappear. However, there is one last modification we need to make, to prevent the MFC framework from attempting to free our assigned m_pszHelpFilePath pointer. This can be done by setting that to nullptr in the MyApp class override of ExitInstance:
int MyApp::ExitInstance()
{
// <your other exit-time code>
m_pszHelpFilePath = nullptr;
return CWinApp::ExitInstance(); // Call base class
}
However, this may seem like much ado about nothing and, as others have said, you may be justified in simply supressing the warning.
Technically, you can take advantage of the fact that new / delete map to usual malloc/free by default in Visual C++, and just go ahead and replace. The portability won't suffer much as MFC is not portable anyway. Sure you can use unique_ptr<TCHAR[]> instead of direct new / delete, like this:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
std::unique_ptr<TCHAR[]> str_old(m_pszHelpFilePath);
auto str_new = std::make_unique<TCHAR[]>(strHelp.GetLength() + 1);
_tcscpy_s(str_new.get(), strHelp.GetLength() + 1, strHelp.GetString());
m_pszHelpFilePath = str_new.release();
str_old.reset();
For robustness for replaced new operator, and for least surprise principle, you should keep free / strdup.
If you replace multiple of those CWinApp strings, suggest writing a function for them, so that there's a single place with free / strdup with suppressed warnings.

finer-grained control than with LD_PRELOAD?

I have a dynamically linked ELF executable on Linux, and I want to swap a function in a library it is linked against. With LD_PRELOAD I can, of course, supply a small library with a replacement for the function that I compile myself. However, what if in the replacement I want to call the original library function? For example, the function may be srand(), and I want to hijack it with my own seed choice but otherwise let srand() do whatever it normally does.
If I were linking to make said executable, I would use the wrap option of the linker but here I only have the compiled binary.
One trivial solution I see is to cut and paste the source code for the original library function into the replacement - but I want to handle the more general case when the source is unavailable. Or, I could hex edit the needed extra code into the binary but that is specific to the binary and also time consuming. Is something more elegant possible than either of these? Such as some magic with the loader?
(Apologies if I were not using the terminology precisely...)
Here's an example of wrapping malloc:
// LD_PRELOAD will cause the process to call this instead of malloc(3)
// report malloc(size) calls
void *malloc(size_t size)
{
// on first call, get a function pointer for malloc(3)
static void *(*real_malloc)(size_t) = NULL;
static int malloc_signal = 0;
if(!real_malloc)
{
// real_malloc = (void *(*)(size_t))dlsym(RTLD_NEXT, "malloc");
*(void **) (&real_malloc) = dlsym(RTLD_NEXT, "malloc");
}
assert(real_malloc);
if (malloc_signal == 0)
{
char *string = getenv("MW_MALLOC_SIGNAL");
if (string != NULL)
{
malloc_signal = 1;
}
}
// call malloc(3)
void *retval = real_malloc(size);
fprintf(stderr, "MW! %f malloc size %zu, address %p\n", get_seconds(), size, retval);
if (malloc_signal == 1)
{
send_signal(SIGUSR1);
}
return retval;
}
The canonical answer is to use dlsym(RTLD_NEXT, ...).
From the man page:
RTLD_NEXT
Find the next occurrence of the desired symbol in the search
order after the current object. This allows one to provide a
wrapper around a function in another shared object, so that,
for example, the definition of a function in a preloaded
shared object (see LD_PRELOAD in ld.so(8)) can find and invoke
the "real" function provided in another shared object (or for
that matter, the "next" definition of the function in cases
where there are multiple layers of preloading).
See also this article.
Just for completeness, regarding editing the function name in the binary - I checked and it works but not without potential hiccups. E.g., in the example I mentioned, one can find the offset of "srand" (e.g., via strings -t x exefile | grep srand) and hex edit the string to "sran0". But names of symbols may be overlapping (to save space), so if the code also calls rand(), then there is only one "srand" string in the binary for both. After the change the unresolved references will then be to sran0 and ran0. Not a showstopper, of course, but something to keep in mind. The dlsym() solution is certainly more flexible.

Should I use CString::Format or sprintf_s

I have 2 code like this
Code 1: CString::Format method
CString cStr;
char* ToString(CString pszFormat, ...)
{
va_list argList;
va_start(argList, pszFormat);
cStr.FormatV(_T(pszFormat), argList);
va_end(argList);
return (LPTSTR)(LPCTSTR)cStr;
//Note that this will return the pointer to the cstring content
}
Code 2: sprintf_s method
char strChar[100];
char* ToString(char const* const _Format, ...)
{
va_list argList;
va_start(argList, _Format);
vsprintf_s(strChar, _Format, argList);
va_end(argList);
return strChar;
//Note that this will return the pointer to the string content
}
In code 1, I feel totally safe - I don't have to afraid about the length maybe too long. But I'm afraid that code 1 may reduce the performance. I don't know if it may cause memory leak or not. And I think that if Cstring has dynamic length, maybe it will allocate and free memory like no one business.
So I come up with code 2. But in code 2, I face the risk if I pass the _Format too long - like string that has length as 1000 - then the program will crash with 'buffer too small' error.
I don't know which one is better: CString::Format or sprintf_s ??? If sprintf_s really increase performance and CString::Format is bad for performance, then I'll take more effort to prevent 'buffer too small' in sprintf_s. But if sprintf_s not worth it - I'll take CString::Format.
Thank for reading.
If you are worried that the buffer in strChar might overflow, then why not simply use vsnprintf_s(). The second argument will restrict the number of characters written to the output buffer. You can modify your 'ToString()' function to receive this extra sizeOfBuffer field and pass it on to vsnprintf_s().
See [https://msdn.microsoft.com/en-us/library/d3xd30zz.aspx][1] for the details and other ways to prevent a buffer overrun.

junk values in a LPTSTR string

I wrote a function to return the extension from a path, It looks like below:
LPTSTR GetExtension(LPCTSTR path1)
{
CString str(path1);
int length = str.ReverseFind(L'.');
str = str.Right(str.GetLength()-length);
LPTSTR extension= str.GetBuffer(0);
str.ReleaseBuffer();
return extension;
}
I checked the statement and found that extension have a valid value(.txt) while returning but when i use the following statement in main method like below
LPTSTR extension = GetExtension(L"C:\\Windows\\text.txt");
The variable extension is having the following junk values:
ﻮ
ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ䞐瀘嗯᠀骰PꬰP⚜叕u
Can anyone tell me what is the reason behind it?
You are returning a pointer to a released buffer. And the buffer is a local variable of the function. Both big no-nos. Change the signature to
size_t GetExtension(LPCTSTR path, LPTSTR buffer, size_t bufferSize)
so that you can copy the result into buffer.
Or return a CString or std::wstring, you're using C++, not C. Using TCHAR is also a heavily outmoded way to handle strings, the last non-Unicode version of Windows died a timely death 12 years ago.
I dont have my compiler with me, but may be you are probably getting the buffer and storing a location of it. Then you release it while LPTSTR is still pointing to one location.
Or may be LPTSTR is on the stack while while you look at it inside the function. On exiting the function you are loosing it.

CString::Format() causes debug assertion

Cstring::Format causes debug assertion in visual studio 2008 at vsprintf.c line 244 with "buffer too small".
//inside the function.
somefile.Open (//open for mode read) //somefile is CFile.
char* buff = new [somefile.GetLength()];
somefile.Read ((void*)buff, somefile.GetLength());
CString cbuff;
cbuff.Format ("%s",buff); //this line causes the debug assertion.
//and so on
Any idea why CString::Format() causes "buffer too small" error ? This doesn't always get debug assertion error.
An alternate solution is:
somefile.Open (//open for mode read) //somefile is CFile.
int buflen = somefile.GetLength();
CString cbuff;
somefile.Read ((void*)cbuff.GetBuffer(buflen), buflen);
cbuff.ReleaseBuffer();
It reads directly into a string buffer instead of the intermediate variable. The CString::GetBuffer() function automatically adds the extra byte to the string which you forgot to do when you allocated the "new char[]".
string end with '\0'
so buffer size will not be enough
The problem is that CFile::Read() does not guarantee that it reads as much data as you ask for. Sometimes it's reading less and leaving your buffer without a null terminator. You have to assume that you might only get one byte on each read call. This will also crash sometimes, when an un-readable memory block immediately follows your buffer.
You need to keep reading the file until you get to the end. Also, the null terminator is generally not written to the file at all, so you shouldn't assume that it will be read in but rather ensure that your buffer is always null-terminated no matter what is read.
In addition, you shouldn't use the file size as the buffer size; there's no reason to think you can read it all in at once, and the file size might be huge, or zero.
You should also avoid manual memory management, and instead of new[]/delete[], use a vector, which will ensure that you don't forget to free the buffer or use delete instead of delete[], and that the memory is released even in case of an exception. (I wouldn't recommend using CString or CFile either, for that matter, but that's another topic...)
// read from the current file position to the end of
// the file, appending whatever is read to the string
CString ReadFile(CFile& somefile, CString& result)
{
std::vector<char> buffer(1024 + 1);
for (;;)
{
int read = somefile.Read(&buffer[0], buffer.size() - 1);
if (read > 0)
{
// force a null right after whatever was read
buffer[read] = '\0';
// add whatever was read to the result
result += &buffer[0];
}
else
{
break;
}
}
}
Note that there's no error handling in this example.

Resources