In my program I have a char* buffer which is being used inside a thread sequence which carries text from one function into another, but the text is different through the run-time in my program. The question that I am asking is, which function can I use to clear the previously used text out of the char* ?
For example, I have the following code:
int GameUtils::GetText(char *text)
{
for(int i=0; i<LINES_OF_TEXT; i++)
{
if(line[i][0]!=0)
{
strcpy(text, line[i]);
MessageBox(0, text, 0, 0);
line[i][0]=0;
return 1;
}
}
return 0;
}
line is defined as such: char GameUtils::line[2][32];
When the messagebox is output on the screen (while code is executed). I get some random junk characters in the text field. Can anyone tell me why this is?
Also! Note that line is assigned as stated in my previous question.
The function which assigns line is:
for (int x=0; x<((int)(strlen(szLine)+1)); x++)
{
if (szLine[x]==' ' || szLine[x]=='\0')
{
m=x;
for (y=0, z=n; z<m; y++, z++)
{
line[w][y]=szLine[z];
}
n=x+1;
w++;
}
}
The above function simply takes a parameter szLine[512] which is passed from my game interface and splits up the line assorting each space as a new parameter.
As an example, if inside the game the user states the line:
/msg <player> <message>
The function would assign each separate word to the line variable, respectively.
Such that, after the function is finished. line would look like
line[0] = /msg
line[1] = <player>
line[2] = <message>
So my question overall is as follows. Am I taking the cleaniest/most appropriate approach at this problem? If not, can anyone show me a better way to approach this problem? Also, can anyone explain to me why I am getting junk characters in the text parameter when the messagebox executes?
EDIT
After viewing the preview of my submitted question; I noticed I have defined char GameUtils::line[2][32] as a 2-dimensional array. I had done this earlier to test. I now understand this could have been the cause to my problem. Can anyone suggest me a replacement for this if I don't know the exact amount of parameters that could be inputted into this variable. The user can issue different requests each time like "/help ", "/msg ", "/whois ", "/create "...
When memory is allocated it isn't zeroed first (at least when using malloc, calloc - however, does zero memory first).
To clear a buffer in C (rather than C++), you have a few options:
Allocate the buffer using calloc instead of malloc.
Use Win32's ZeroMemory function
Use memset, like so: memset( buffer, 0x00, BUFFER_SIZE );
However you're clearly using C++, so you should use the standard library and C++ idioms rather than C-style things, that means using std::string instead of char*, and if you have to use buffers directly then the C++ way of zeroing (or filling) an array or buffer is std::fill.
First off, I would avoid using double dimensional arrays if you can avoid it. Maybe look into std::string:
http://www.cplusplus.com/reference/string/string/
As for why a char array might have "random junk" in it, when you allocate a buffer in C++, it always has data in it. You have to manually set the data to 0 if you want it to be empty. So when you first allocate an array, it might be a idea to zero out all the values first.
Related
I'm using a dynamic C-style string to read in data from a file, but for some reason when I dynamically allocate the C-style string using the given length, it comes out with four extra characters that can be seen using strlen(). The junk in these empty spaces is added on to the end of the read-in string and is displayed on cout. What on earth could be causing this, and how can I fix it?
The C-style string is declared in the beginning of the code, and is used one time before this. The time it is used before this it is also too large, but in that case it does not add extra information to the end. After use, it is deleted and not used again until this point. I'm pretty confused as I have not had this happen or had a problem with it before.
// Length read as 14, which is correct
iFile.read(reinterpret_cast<char *>(&length), sizeof(int));
tempCstring = new char[length]; // Length still 14
cout << strlen(tempCstring); // Console output: 18
// In tempCstring: Powerful Blockýýýý
iFile.read(reinterpret_cast<char *>(tempCstring), length);
// Custom String class takes in value Powerful Blockýýýý and is
// initialized to that
tempString = String(tempCstring);
// Temp character value takes in messed up string
temp.setSpecial(tempString);
delete[] tempCstring; // Temp cString is deleted for next use
When written to file:
// Length set to the length of the cString, m_special
length = strlen(chars[i].getSpecial().getStr());
// Length written to file. (Should I add 1 for null terminator?)
cFile.write(reinterpret_cast<char *>(&length), sizeof(int));
// String written to file
cFile.write(reinterpret_cast<char *>(chars[i].getSpecial().getStr()), length);
Whenever you see junk at the end of a string, the problem is almost always the lack of a terminator. Every C-style string ends in a byte whose value is zero, spelled '\0'. If you did not place one yourself, the standard library keeps reading bytes in memory until it sees a random '\0' that it sees in memory. In other words, the array is read beyond its bounds.
Use memset(tempCString,0,length) in order to zero out the memory following your allocation. However, this is not the soundest solution, as it is covering the real problem under the rug. Show us the context in which this code is used. Then I will be able to say where in your algorithm you will need to insert the null terminator: tempCString[i] = 0, or something like that. Nonetheless, from what you have posted, I can tell that you need to allocate one more character to make room for the terminator.
Also, since you are using C++, why not use std::string? It avoids these kinds of problems.
I have been trying to return an array of strings for a function for a couple of days to no avail. While I was searching around StackOverflow, I found that it would be a better idea to have a parameter that will be assigned the value of an array. So, here is my code example (not the actual usage, but a mockup of how I am trying to use the function). I am sorry if the code is a bit sloppy. I have been testing things out with it for a while.
void splitOn(string message, string delim, string***toCh) {
string** rString = new string*;
string lArr[numberOf(message, delim)+1];
for(int index=0; index<numberOf(message, delim)+2; index++) {
lArr[index]=message.substr(0, message.find(delim)).c_str();
message = message.substr(message.find(delim)+1, message.length());
rString[index]=&lArr[index];
cout << "IN LOOP "<<*rString[index]<<endl;
}
rString[numberOf(message, string(delim))] = &message;
toCh=&rString;
}
int main(){
string***arr;
splitOn("fox.over.lazy.dog", ".", arr);
cout << **arr[0]<<endl;
Note:
numberOf() takes a string and a delimiter(string) and returns how many times the delimiter is found within the string.
strings are from std::string
lArr (the local array within the loop) and *rString all give correct output.
Although I am trying to assign the array to a parameter, learning how to return an array is more appealing to me.
I could hack this together with a file and getLine(), but I would prefer to learn how to properly do this.
You're trying to return local variables, which will never work. You and your caller need to agree on how to allocate the return value. In C++ as the commenters mention this would normally be done by passing a reference to a vector to handle your allocation for you.
In C you have two options, you can either get the caller to pass in a big enough allocation, or use multiple calls to malloc in the callee (not forgetting the calls to free in the caller!)
For instance, if you pass a writable character array, you can simply overwrite the separator characters with null characters to split it up into individual strings without having to allocate new copies.
How to find out the lenght of an array of chars that is not null terminated/zero terminated or anything like that?
Because I wrote a writeFile function and I wanna get rid of that 'len' parameter.
int writeFile(FILE * handle, char * data, int len)
{
fseek(handle, 0, SEEK_SET);
for(int i=0; i <= len; i++)
fputc(data[i], handle);
}
You cannot get rid of the len parameter. The computer is not an oracle to guess your intentions. But you can use the fwrite() function which will write your data much more efficiently than fputc().
there is no portable way*, that is why sentinel values like null terminators are used.
In fact, its better to specify a length parameter, as it allows partial writes from data buffers (though in your case I would use a size_t/std::size_t for the length).
*you could try using _msize on windows, but it will lead to tears.
#define writeFile(handle, data) writeFileImpl(handle, data, sizeof data)
As Seith Carnegie commented and others answered, you cannot do that (getting the length of any array of char).
Some C libraries provide you with an extension giving an (over-sized) estimate of the length of heap-allocated memory (e.g. pointers obtained by malloc).
If you uses Boehm's garbage collector (which is very useful!), it gives you in <gc/gc.h> the GC_size function.
But when the array of char is inside a structure, or on the call stack, there is no way to get its size at runtime. Only your program knows it.
You can't get rid of the len parameter unless you have another way of determining the length of your data (usually by using a null terminator). This is because C and C++ don't store the length of the data. Furthermore, programmers might appreciate the len parameter. You don't always want to write out all the bytes in your array.
My boss told me to look at the following code and tell him what the potential security vulnerabilities were. I'm not very good at this kind of thing, since I don't think in the way of trying to hack code. All I see is that nothing is declared private, but other than that I just don't know.
#define NAME_SIZE (unsigned char) 255
// user input should contain the user’s name (first name space
// middle initial space last name and a null
// character), and was entered directly by the user.
// Returns the first character in the user input, or -1 if the method failed.
char poor_method(char* user_input, char* first, char *middle, char* last)
{
char*buffer;
char length;
// find first name
buffer = strtok(user_input, " ");
if(buffer==0)
{
return -1;
}
length = strlen(buffer);
if(length <= NAME_SIZE)
{
strcpy(first, buffer);
}
// find middle name
buffer = strtok(NULL, " ");
if(buffer==0)
{
return-1;
}
if(middle)
*middle = buffer[0];
// find last name
buffer = strtok(NULL, "\0");
length = strlen(buffer);
if(length <= NAME_SIZE)
{
strcpy(last, buffer);
}
// Check to make sure that all of the user input was used
buffer = strtok(NULL, "\0");
if(buffer != NULL)
{
return-1;
}
return first[0];
}
What security vulnerabilities are there?
Get good at writing secure code
You most likely don't want systems that you are responsible for finding their way onto bugtraq or cve. If you don't understand it, be honest with your boss. Tell him you don't understand and you want to work on it. Pick up Writing Secure Code. Read it, learn it, love it. Asking this question on SO and giving your boss the answer definitely doesn't help you in the long run.
Then look at the sample code again :)
What I saw (by no means a complete list):
There's no guarantees you're going to get a char pointer which points to a null-terminating string (unless you're allowed to make that assumption, not really a safe one to make).
strtok and strcpy are the C way of doing things and come with the fun stuff of programming C code. If you must use them, so be it (just make sure you can guarantee you're inputs to these functions will indeed be valid). Otherwise, try switching your code to use std::string and the "C++ way" (as Cat Plus Plus put it)
I'm assuming this is a typo:
charpoor_method(
You're missing a space between char and poor_method(
You're not checking if first or last are indeed valid pointers (unfortunately, the best you can do is to check them against NULL).
There's no guarantee that the buffers first or last can indeed hold whatever you're copying to them.
Another typo:
returnfirst[0];
missing space between return and first[0]
Learning to write secure code is something that's very important to do. Follow Brecht's advice and get good at it.
Ok strtok assumes user_input is NULL terminated, this might not be true.
charlength = strlen(buffer);
if(length <= NAME_SIZE)
{
strcpy(first, buffer);
}
charlenght here is undeclared, so is length, they should be declared as unsigned int.
strlen wont count the '\0' as a part of the length, so later strcpy will copy the '\0' to whatever is after First if the len of buffer is 255 + 1('\0')
Also is unknown if char *first size is, it should be NAME_SIZE but the comparisson should be
length <= NAME_SIZE - 1
or allocate char *first to NAME_SIZE + 1
I'd probably rewrite the whole thing, is quite ugly.
Rather than using strcpy(), use strncpy() with a specific length parameter, as that function, like strtok(), assumes a NULL-terminated buffer for the source, and that may not be the case, giving you a buffer overflow for the data copied into the buffer pointed to by either first or last. Additionally, you have no idea how long the buffers are that have been allocated for first and last ... Don't assume that the user of your function has properly allocated enough memory to copy into unless they've passed you a parameter telling you there are enough memory slots in the buffers. Otherwise again, you could (and most likely will) end-up with buffer overflows.
Also you may want to use the restrict keyword if you're using C99 in order to prevent the caller of your function from aliasing the same memory location for buffer, first, and last.
Hey everyone, thanks for taking the time to address my problem. I've looked at so much material at this point that I've just started getting more and more confused. Basically, I'm writing a simple segment of code that parses a string. Please understand that my question is NOT about parsing. I am using C++ and have never used C before and possess a little bit of c++ experience (introductory experience, I'm still a newbie).
struct parsedString{
char chunk1[50];
char chunk2[10];
char chunk3[50];
};
main(char* bigstring)
{
parsedString ps;
ps = parseMe(bigString)
cout << ps.chunk1 << endl;
cout << ps.chunk2 << endl;
cout << ps.chunk3 << endl;
}
parsedString parseMe(char* stringToParse)
{
char* parseStr = stringToParse;
parsedString ps;
ps.chunk1 = first x chars;
ps.chunk2 = next y chars;
ps.chunk3 = last z chars;
return ps;
}
Obviously this is not working code, I didn't want to throw up all the extra stuff since it would be tougher to read through and I'm pretty sure my problem is a newbie c/c++ problem and something about memory allocation or something like that...
Basically when the main function gets to printing the strings from the parsedString it prints out exactly what I want it to, plus garbage characters. I'm entering the values for each array ps.chunk using
ps.chunk1[i] = *parseStr
since parseStr gets me each individual character. I can't figure out where the garbage characters are coming from, does it have something to do with how I am accessing the big string? Originally I used char in the struct instead of arrays and when I printed from within the parseMe() function they would come out great but they would turn into gibberish when I accessed it from the main function. Any help is appreciated, thanks so much.
If something is unclear please let me know I'll do my best to elaborate.
It's not clear why you're trying to do this with '\0' terminated
strings, when C++ has a perfectly usable string class, but
supposing some pedagogical reasons: are your strings '\0'
terminated? How do you extract and copy the first x chars into
ps.chunk1? How do you ensure that it has a '\0'?
If you really want to get exactly n characters, you have to:
assert(strlen(parseStr) >= n);
, copy them into the target (which must contain at least n+1 char's),
memcpy(ps.chunk1, parseStr, n);
, and add the final '\0':
ps.chunk1[n] = '\0';
(And, of course, advance parseStr: parseStr += n;)
Or you can simply use std::string everywhere, and write
something like:
ps.chunk1(stringToParse.substr(startPosition, length));
As pointed out by others, you should use std::string to represent strings, and save yourself all the trouble. This could look like this:
struct parsedString{
std::string chunk1;
std::string chunk2;
std::string chunk3;
};
parsedString parseMe(const std::stirng & stringToParse) {
parsedString result;
// just an example - this assigns the first two characters of stringToParse
// to chunk1
result.chunk1 = stringToParse.substr(0, 2);
// get the other chunks
return result; // return the result
}
The above code should illustrate the usage. You can find more information on std::string here.
This could be happening due to a couple of reasons.
When you declare parsedString ps; it would be good to initialize the structure and make sure that you are receiving clean memory blocks to work with.parsedString ps = {0}; Some platforms don't do this and it's up to you to zero the memory before using it.
char* strings must end with the \0 character. This character signals the end of a char*. This is mandatory! Not inserting it at the end of the string will most probably make the print operation (for instance) display contents beyond the limits of the array giving you garbage characters. This is automatically achieved by zeroing all the struct as I suggest above.