However, if the second function is replaced by a member function of one of my classes,
{
MyClass myobject;
CString x;
x = StringFunction1() + myobject.StringFunction();
MessageBox(x);
}

then no concatenation happens; the messagebox just shows "ONE".

class MyClass
{
public:
MyClass();
CString StringFunction();
};

CString MyClass::StringFunction()
{
return CString("CSF");
}

I've looked on various google pages, and people keep saying you can't do this because you're returning a pointer to a local variable that no longer exists. Why ? Surely "return" has something like operator= semantics, in that it constructs a copy of whatever it is, in the callER's stack space ?

The problem is actually an interesting property of how CString works, combined with a misunderstanding with how VerQueryValue() works.
First, VerQueryValue() - it is returning a buffer size that includes

It must work for VC6 as well. Please post the exact code where you got the issue. The above seems to be edited here in EE as it wouldn't compile. I assume your original code has some crudities by using same names for member variables, arguments or global variables or same names for member functions and global functions.

Note, I don't see a value in naming global functions similar or equal to member functions. But if you do so, it is a good chance to shoot yourself into the foot.

Non-static member functions should somehow refer to (non-static) member data. If not make them static functions so that they can be used without an object.

OK. When I create a minimal program such as I posted originally, the concatenation does indeed work correctly. However, my main program still does not. It's impractical to split down the big program into a form suitable for posting here, but I'll do so if I can get it to a form which demonstrates the problem.

What happens is that the window text gets set to the contents of vi.GetProductName(); everything after that is lost. However, when I change the vi.GetProductName() definition to return a dummy value, it all works correctly.

So, it appears that my member function vi.GetProductName() is doing something weird with the return value.

vi is an instance of the class VersionInformation, which I created. It looks like this:

I seem to remember having a problem with const-ness in this function; I had to make something non-const even though it was const.

The problem is probably here. Look at the right side of the assignment.

The left argument for the + operation is a const char* pointer. The right side is a CString which has a implicit cast operator to a const char* as well. Hence, the operator + adds some pointers and the result is a pointer as well but pointing somewhere into the (virtual) memory.

What you need is

t1 = CString("(DEBUG) ") + t1;

Now the left operand is a CString and the compiler knows to take the CString::operator+ instead of adding pointers.

The problem is actually an interesting property of how CString works, combined with a misunderstanding with how VerQueryValue() works.

First, VerQueryValue() - it is returning a buffer size that includes the NULL terminator, not the size that strlen() would return on the buffer - it is one more.

You have code to copy the buffer to a CString one character at a time in your get_string() function:

for (unsigned int i=0;i<bs2;i++)
{
rv += ((char*)pb2)[i];
}

The problem is that bs2 contains the size of the buffer (including the NULL), not the number of characters.

So when you get to last character, you are essentially doing

rv += '\0';

What many people don't know is that CStrings happily work with binary data. And they keep track of their length on their own (that is, they don't use a strlen() equivalent to return the length). So when you append a NULL, you are actually embedding a NULL into your string data.

All of your other concatenatations are working correctly, but because the CString has an embedded NULL, only the part in front of the NULL gets displayed. If you look at the CString in a memory window you will see all of the characters there.

Solution:

Instead of looping through the characters and appending one by one, just assign the buffer:

> The left argument for the + operation is a const char* pointer. The right side is a CString which has a implicit cast operator to a const char* as well. Hence, the operator + adds some pointers and the result is a pointer as well but pointing somewhere into the (virtual) memory.

This is incorrect, there are multiple friend operator+ functions defined that allow CString's and pointers to be used in either order.

If it returns a const char* or a LPCSTR (what is a const char* as well) then you were adding two pointers. You only can concatenate using the + operator if the left argument of any + operation is a CString.

>>>> This is incorrect, there are multiple friend operator+ functions
I know that I added such an operator to my private string class. I don't know for sure that CString has such an operator which allows to add a left hand char pointer. I mean to remember that I recently had problems with that but I may be wrong.

Doesn't matter because vi.GetProductName() is returning a CString, you can have as many pointers to the right of the CString as you want, they are processed from left to right one at a time, with a CString as the result of each intermediate step. Walk through it in the debugger if you don't believe me.

Anyway, as I posted above the problem has nothing to do with faulty pointer arithmetic.

Thank you for pointing out my obvious error. I did know that CStrings maintained their own length and could work with binary data but, combined with my misunderstanding about VerQueryString(), my brain didn't consider it !

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008. These same feature are in the MFC libraries that come with Visual …

Introduction:
Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information.
Continuing from the first article about sudoku. There we have designed the application and put a lot of user int…