I'm trying to use the StringCchCat function:
HRESULT X;
LPWSTR _strOutput = new wchar_t[100];
LPCWSTR Y =L"Sample Text";
X = StringCchCat(_strOutput, 100, Y);
But for some reason I keep getting the "E_INVALIDARG One or more arguments are invalid." error from X. _strOutput Is also full of some random characters.
This is actually part of a bigger program. So what I'm trying to do is to concatenated the "sample text" to the empty _strOutput variable. This is inside a loop so it is going to happen multiple times. For this particular example it will be as if I'm assigning the Text "Sample Text" to _strrOutput.
Any Ideas?
If it's part of a loop, a simple *_strOutput = 0; will fix your issue.
If you're instead trying to copy a string, not concatenate it, there's a special function that does this for you: StringCchCopy.
Edit: As an aside, if you're using the TCHAR version of the API (and you are), you should declare your strings as TCHAR arrays (ie LPTSTR instead of LPWSTR, and _T("") instead of L""). This would keep your code at least mildly portable.
String copy/concat functions look for null terminators to know where to copy/concat to. You need to initialize the first element of _strOutput to zero so the buffer is null terminated, then you can copy/concat values to it as needed:
LPWSTR _strOutput = new wchar_t[100];
_strOutput[0] = L'\0`; // <-- add this
X = StringCchCat(_strOutput, 100, Y);
I'm writing this answer to notify you (so you see the red 1 at the top of any Stack Overflow page) because you had the same bug yesterday (in your message box) and I now realize I neglected to say this in my answer yesterday.
Keep in mind that the new[] operator on a built-in type like WCHAR or int does NOT initialize the data at all. The memory you get will have whatever garbage was there before the call to new[], whatever that is. The same happens if you say WCHAR x[100]; as a local variable. You must be careful to initialize data before using it. Compilers are usually good at warning you about this. (I believe C++ objects have their constructors called for each element, so that won't give you an error... unless you forget to initialize something in the class, of course. It's been a while.)
In many cases you'll want everything to be zeroes. The '\0'/L'\0' character is also a zero. The Windows API has a function ZeroMemory() that's a shortcut for filling memory with zeroes:
ZeroMemory(array, size of array in bytes)
So to initialize a WCHAR str[100] you can say
ZeoMemory(str, 100 * sizeof (WCHAR))
where the sizeof (WCHAR) turns 100 WCHARs into its equivalent byte count.
As the other answers say, simply setting the first character of a string to zero will be sufficient for a string. Your choice.
Also just to make sure: have you read the other answers to your other question? They are more geared toward the task you were trying to do (and I'm not at all knowledgeable on the process APIs; I just checked the docs for my answer).
Related
SOLUTION Apparently, the wgetstr function does not make a new buffer. If the second argument is called data and has size n and you give an input of more than n characters, it will access and overwrite parts in memory that do not belong to data, such as the place in memory where cursorY is stored. To make everything work, I declared data with char data[] = " "; (eight spaces) and wrote wgetnstr(inputWin, data, 8);.
--------------------------------------------------------------------------------------------------------------
It seems that the ncurses function wgetstr is literally changing the values of my variables. In a function called playGame, I have a variable called cursorY (of type int) which is adjusted whenever I press the up- or down-arrow on my keyboard (this works fine).
Please take a look at this code (inputWin is of type WINDOW*):
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
wgetstr(inputWin, data);
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
Suppose I move the cursor to the 6th row and then press Enter (which causes this piece of code to be executed). There are two things I can do:
Input just 1 character. After both refresh calls, the value 6 is shown on the screen (at position (0, 0)).
Input 2 or more characters. In this case, after the first refresh call I simply get 6, but after the second, I magically get 0.
The first two lines after the code above are
noecho();
_theView -> _theActualSheet -> putData(cursorY-1, cursorX/9 - 1, data);
(don't worry about the acutal parameters: the math regarding them checks out). While I'm in putData, I get a Segmentation fault, and gdb says that the first argument of putData was -1, so then cursorY had to be 0 (the first two arguments of putData are used to access a two-dimensional array using SheetCells[row][column], where row and column are, respectively, the first and second formal parameter of putData).
Clearly, wgetstr modifies the value of cursorY. The name of the latter variable doesn't matter: changing it to cursorrY or something weird like monkeyBusiness (yes I've tried that) doesn't work. What sort of works is replacing the piece of code above with
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
int a = cursorY;
wgetstr(inputWin, data);
cursorY = a;
mvprintw(0, 0, (to_string(cursorY)).c_str());
refresh();
usleep(500000);
In both cases I see 6 at the top-left corner of my screen. However, know the string is acting all weird: when I type in asdf as my string, then move to the right (i.e., I press the right key on my keyboard), then type in asdf again, I get as^a.
So basically, I would like to know two things:
Why the HELL is wgetstr changing my variables?
Why is it only happening when I input more than 1 character?
What seems to be wrong with wgetstr in general? It seems terrible at handling input.
I could try other things (like manually reading in characters and then concatenating data with them), but wgetstr seems perfect for what I want to do, and there is no reason I should switch here.
Any help is much appreciated. (Keep in mind: I specifically want to know why the value of cursorY is being changed. If you would recommend not using wgetstr and have a good alternative, please tell me, but I'm most interested in knowing why cursorY is being altered.)
EDIT The variable data is of type char[] and declared like so: char data[] = "". I don't "clear" this variable (i.e., remove all "letters"), but I don't think this makes any difference, as I think wgetstr just overrides the whole variable (or am I terribly wrong here?).
The buffer you provide for the data, data, is defined as being a single character long (only the null-terminator will be there). This means that if you enter any input of one or more characters, you will be writing outside the space provided by data, and thus overwrite something else. It looks like cursorY is the lucky variable that got hit.
You need to make sure that data is at least big enough to handle all inputs. And preferably, you should switch to some input function (like wgetnstr) that will let you pass the size of the buffer, otherwise it will always be possible to crash your application by typing enough characters.
wgetstr expects to write the received characters to a preallocated buffer, which should be at least as long as the expected input string. It does not allocate a new buffer for you!
What you've done is provide it with a single byte buffer, and are writing multiple bytes to it. This will stomp over the other variables you've defined in your function after data, such as cursorY, regardless of what it is called. Any changes to variables will in turn change the string that was read in:
int a = cursorY;
wgetstr(inputWin, data);
cursorY = a;
will write an int value into your string, which is why it is apparently getting corrupted.
What you should actually do is to make data actually long enough for the anticipated input, and ideally use something like wgetnstr to ensure you don't walk off the end of the buffer and cause damage.
I have a class property which is an array of strings (std::string command[10]). When I assign some string value to it, it stop the program execution. As you can see below I've a string variable tempCommandStr which I assign to my property. I don't know what the error could be, but I've the print statement after assignment which is never executed, while the one preceding it is.
//Declared in class header
std::string command[10];
// Part of function which is causing problem.
string tempCommandStr(commandCharArray);
printf("%s\n", tempCommandStr.c_str()); // Prints fine.
this->command[i] = tempCommandStr; // Something goes wrong here. i is set to some correct value, i.e. not out of range.
printf("%s\n", this->command[i].c_str()); // Never prints. Also program stops responding.
// I noticed that getting any value from the array also stops the execution.
// Just the following statement would stop the program too.
printf("%s\n", this->command[i].c_str());
It's not just this property, I also have another array which has the same problem. What could be causing this? What's actually going wrong (look at edit)? Is there another better way to do this?
I'm running the program on an MBED so I've limited debugging options.
EDIT:
I found the problem, I was cleaning the array before using to remove any previous values by memset(command, 0, sizeof(command));. This is was causing the problem. Now I use the clear function on each item in array as following. This fixed the execution problem.
for (int i = 0; i < sizeof(command)/sizeof(*command); i++){
command[i].clear();
}
Question: Why does setting the string array to 0 using memset makes it unusable?
Why does setting the string array to 0 using memset makes it unusable?
Because you're obliterating the values held in the string class, overwriting them all with 0s. A std::string has pointers to the memory where it's storing the string, character count information, etc. If you memset() all that to 0, it's not going to work.
You're coming from the wrong default position. Types where 'zeroing out' the memory is a meaningful (or even useful) operation are special; you should not expect any good to come from doing such a thing unless the type was specifically designed to work with that.
I am re-writing a C++ method from some code I downloaded. The method originally took a PCWSTR as a parameter and then prompted the user to enter a file name. I modified the method to take two parameters (both PCWSTR) and not to prompt the user. I am already generating the list of files somewhere else. I am attempting to call my new (modified) method with both parameters from my method that iterates the list of files.
The original method prompted the user for input using a StringCBGetsW command. Like this...
HRESULT tst=S_OK; //these are at the top of the method
WCHAR fname[85] = {0}; //these are at the top of the method
tst = StringCbGetsW(fname,sizeof(fname));
The wchar fname gets passed to another iteration method further down. When I look at that method, it says it's a LPCWSTR type; I'm assuming it can take the WCHAR instead.
But what it can't do is take the PCWSTR that the method got handed. My ultimate goal is to try not prompt the user for the file name and to take instead the filename that was iterated earlier in another method.
tl;dr. I have a PCWSTR and it needs to get converted to a WCHAR. I don't know what a WCHAR [] is or how to do anything with it. Including to try to do a printf to see what it is.
PS...I know there are easier ways to move and copy around files, there is a reason I'm attempting to make this work using a program.
First, let's try to make some clarity on some Windows specific types.
WCHAR is a typedef for wchar_t.
On Windows with Microsoft Visual C++, it's a 16-bit character type (that can be used for Unicode UTF-16 strings).
PCWSTR and LPCWSTR are two different names for the same thing: they are basically typedefs for const wchar_t*.
The initial L in LPCWSTR is some legacy prefix that, read with the following P, stands for "long pointer". I've never programmed Windows in the 16-bit era (I started with Windows 95 and Win32), but my understanding is that in 16-bit Windows there were something like near pointers and far, or long pointers. Now we have just one type of pointers, so the L prefix can be omitted.
The P stands for "pointer".
The C stands for "constant".
The W stands for WCHAR/wchar_t, and last but not least, the STR part stands for "string".
So, decoding this kind of "Hungarian Notation", PCWSTR means const wchar_t*.
Basically, it's a pointer to a read-only NUL-terminated wchar_t Unicode UTF-16 string.
Is this information enough for you to solve your problem?
If you have a wchar_t string buffer, and a function that expects a PCWSTR, you can just pass the name of the buffer (corresponding the the address of its first character) to the function:
WCHAR buffer[100];
DoSomething(buffer, ...); // DoSomething(PCWSTR ....)
Sometimes - typically for output string parameters - you may also want to specify the size (i.e. "capacity") of the destination string buffer.
If this size is expressed using a count in characters (in this case, in wchar_ts), the the usual Win32 Hungarian Notation is cch ("count of characters"); else, if you want the size expressed in bytes, then the usual prefix is cb ("count of bytes").
So, if you have a function like StringCchCopy(), then from the Cch part you know the size is expressed in characters (wchar_ts).
Note that you can use _countof() to get the size of a buffer in wchar_ts.
e.g. in the above code snippet, _countof(buffer) == 100, since buffer is made by 100 wchar_ts; instead, sizeof(buffer) == 200, since each wchar_t is 2 bytes == 16 bits in size, so the total buffer size in bytes is 100 [wchar_t] * 2 [bytes/wchar_t] = 200 [bytes].
I am trying to understand the GetBuffer() function. Looks like it returns you the pointer to the CString, which is confirmed in msdn GetBuffer(). However, I don't understand the example shown in the msdn GetBuffer().
LPTSTR p = s.GetBuffer( 10 );
Is there a reason why it's 10 inside? Can anyone show me the output of the example?
The 10 is the minimum buffer length, so if you call GetBuffer() on a CString of, say, 4 characters it will allocate an LPTSTR 10 chars long, in case you want to strcpy a longer string into that buffer (as they do in the example). The 10 in the example is arbitrary, they could just as easily used 6 (five letters in "Hello" plus the terminating null) or any larger number and it would have worked the same.
In general, though, you'll be better off steering clear of GetBuffer() unless you really need to use it.
Here's the code I want to speed up. It's getting a value from an ADO recordset and converting it to a char*. But this is slow. Can I skip the creation of the _bstr_t?
_variant_t var = pRs->Fields->GetItem(i)->GetValue();
if (V_VT(&var) == VT_BSTR)
{
char* p = (const char*) (_bstr_t) var;
The first 4 bytes of the BSTR contain the length. You can loop through and get every other character if unicode or every character if multibyte. Some sort of memcpy or other method would work too. IIRC, this can be faster than W2A or casting (LPCSTR)(_bstr_t)
Your problem (other than the possibility of a memory copy inside _bstr_t) is that you're converting the UNICODE BSTR into an ANSI char*.
You can use the USES_CONVERSION macros which perform the conversion on the stack, so they might be faster. Alternatively, keep the BSTR value as unicode if possible.
to convert:
USES_CONVERSION;
char* p = strdup(OLE2A(var.bstrVal));
// ...
free(p);
remember - the string returned from OLE2A (and its sister macros) return a string that is allocated on the stack - return from the enclosing scope and you have garbage string unless you copy it (and free it eventually, obviously)
This creates a temporary on the stack:
USES_CONVERSION;
char *p=W2A(var.bstrVal);
This uses a slightly newer syntax and is probably more robust. It has a configurable size, beyond which it will use the heap so it avoids putting massive strings onto the stack:
char *p=CW2AEX<>(var.bstrVal);
_variant_t var = pRs->Fields->GetItem(i)->GetValue();
You can also make this assignment quicker by avoiding the fields collection all together. You should only use the Fields collection when you need to retrieve the item by name. If you know the fields by index you can instead use this.
_variant_t vara = pRs->Collect[i]->Value;
Note i cannot be an integer as ADO does not support VT_INTEGER, so you might as well use a long variable.
Ok, my C++ is getting a little rusty... but I don't think the conversion is your problem. That conversion doesn't really do anything except tell the compiler to consider _bstr_t a char*. Then you're just assigning the address of that pointer to p. Nothing's actually being "done."
Are you sure it's not just slow getting stuff from GetValue?
Or is my C++ rustier than I think...