I've been working with this for about 2 days now. I'm stuck, with a rather simple annoyance, but I'm not capable of solving it.
My programs basicly recieves a TCP connection from a PHP script. And the message which is send is stored in char buffer[1024];.
Okay this buffer variable contains an unique key, which is being compared to a char key[1024] = "supersecretkey123";
The problem itself is that these two does not equal - no matter what I do.
I've been printing the buffer and key variable out just above eachother and by the look they are 100% identical. However my equalisation test still fails.
if(key == buffer) { // do some thing here etc }
So then I started searching the internet for some information on what could be wrong. I later realized that it might be some escape characters annoying me. But I'm not capable of printing them, removing them or even making sure they are there. So that's why I'm stuck - out of ideas on how to make these equal when the buffer variable matches the key variable.
Well the key does not chance, unless the declaration of the key is modified manually. The program itself is recieving the information and sending back information "correctly".
Thanks.
If you're using null terminated strings use proper api - strcmp and its variants.
Additionally size in declaration char key[1024] = "supersecretkey123"; is not needed - either compiler will reduced it or stack/heap memory will be wasted.
If you are using C++ use std::string instead of char []. You cannot compare two char [] in way you try to do this (they are pointers to memory), but it's possible with std::string.
If it's somehow mandatory to use char[] in your case, use strcmp.
Try with if(!strncmp(key,buffer,1024)). See this reference on strncmp.
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 trying to convert a std::string Buffer - containing data from a bitmap file - to std::wstring.
I am using MultiByteToWideChar, but that does not work, because the function stops after it encounters the first '\0'-character. Seems like it interprets it as the end of the string.
When i dont pass -1 as the length-parameter, but the real length of the data in the std::string-Buffer, it messes the Unicode-String up with characters that definetly not appeared at that position in the original string...
Do I have to write my own conversion function?
Or maybe shall i keep the data as a casual char-array, because the special-symbols will be converted incorrectly?
With regards
There are many, many things that will fail with this approach. Among other things, extra bytes may be added to your data without your realizing it.
It's odd that your only option takes a std::wstring(). If this is a home-grown library, you should take the trouble to write a new function. If it's not, make sure there's nothing more suitable before writing your own.
I have a situation where I have a std::string, and I only need characters x to x + y, and I think it would speed it up quite a bit if I instead could somehow do (char*)&string[x], but the problem is all my functions expect a NULL terminated string.
What can I do?
Thanks
Nothing nice can be done. The only trick I can think of is temporarily setting s[x+y+1] to 0, pass &s[x], then restore the character. But you should resort to this ONLY if you are sure this will reasonably boost the performance and that boost is necessary
nothing (if the string you need is in the middle). the speed difference will be utterly trivial unless its being done A LOT (several millions)
Use:
string.c_str() + x;
This assumes your function takes a const char *
If you need actual 0-termination, you'll have to copy.
You have no choice here. You can't create a null-terminated substring without copying or modifying the original string.
You say you "think it would speed it up". Have you measured?
You could overwrite &string[x+y+1] with a NUL, and pass &string[x] to your functions. If you're going to need the whole string again afterward, you can save it for the duration, and restore it when needed.
When I try to do things like this:
char* prefix = "Sector_Data\\sector";
char* s_num = "0";
std::strcat(prefix, s_num);
std::strcat(prefix, "\\");
and so on and so forth, I get a warning
warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead.
Why is strcat considered unsafe, and is there a way to get rid of this warning without using strcat_s?
Also, if the only way to get rid of the warning is to use strcat_s, how does it work (syntax-wise: apparently it does not take two arguments).
If you are using c++, why not avoid the whole mess and use std::string. The same example without any errors would look like this:
std::string prefix = "Sector_Data\\sector";
prefix += "0";
prefix += "\\"
no need to worry about buffer sizes and all that stuff. And if you have an API which takes a const char *, you can just use the .c_str() member;
some_c_api(prefix.c_str());
Because the buffer, prefix, could have less space than you are copying into it, causing a buffer overrun.
Therefore, a hacker could pass in a specially crafted string which overwrites the return address or other critical memory and start executing code in the context of your program.
strcat_s solves this by forcing you to pass in the length of the buffer into which you are copying the string; it will truncate the string if necessary to make sure that the buffer is not overrun.
google strcat_s to see precisely how to use it.
You can get rid of these warning by adding:
_CRT_SECURE_NO_WARNINGS
and
_SCL_SECURE_NO_WARNINGS
to your project's preprocessor definitions.
That's one of the string-manipulation functions in C/C++ that can lead to buffer overrun errors.
The problem is that the function doesn't know what the size of the buffers are. From the MSDN documentation:
The first argument, strDestination,
must be large enough to hold the
current strDestination and strSource
combined and a closing '\0';
otherwise, a buffer overrun can occur.
strcat_s takes an extra argument telling it the size of the buffer. This allows it to validate the sizes before doing the concat, and will prevent overruns. See http://msdn.microsoft.com/en-us/library/d45bbxx4.aspx
Because it has no means of checking to see if the destination string (prefix) in your case will be written past its bounds. strcat essentially works by looping, copying byte-by-byte the source string into the destination. Its stops when it sees a value "0" (notated by '\0') called a null terminal. Since C has no built in bounds checking, and the dest str is just a place in memory, strcat will continue going ad-infinidium even if it blows past the source str or the dest. str doesn't have a null terminal.
The solutions above are platform-specific to your windows environment. If you want something platform independent, you have to wrangle with strncat:
strncat(char* dest, const char* src, size_t count)
This is another option when used intelligently. You can use count to specify the max number of characters to copy. To do this, you have to figure out how much space is available in dest (how much you allocated - strlen(dest)) and pass that as count.
To turn the warning off, you can do this.
#pragma warning(disable:4996)
btw, I strongly recommend that you use strcat_s().
There are two problems with strcat. First, you have to do all your validation outside the function, doing work that is almost the same as the function:
if(pDest+strlen(pDest)+strlen(pScr) < destSize)
You have to walk down the entire length of both strings just to make sure it will fit, before walking down their entire length AGAIN to do the copy. Because of this, many programmers will simply assume that it will fit and skip the test. Even worse, it may be that when the code is first written it is GUARANTEED to fit, but when someone adds another strcat, or changes a buffer size or constant somewhere else in the program, you now have issues.
The other problem is if pSrc and pDst overlap. Depending on your compiler, strcat may very well be simple loop that checks a character at a time for a 0 in pSrc. If pDst overwrites that 0, then you will get into a loop that will run until your program crashes.