dynamic memory allocation to buffer - c++

I am working on visual c++. I am a beginner of c++ and i am in a strange situation that i have "Contents" variable of type-
char FileContents[200000] ;
now i have taken a size of a file using sizeof operator like this
int SizeOfFile =Sizeof(File);
and now i have to copy the data of this file into "Contents" whch has array index 200000.Suppose i do so by
memcpy(FileContents,&File[0],SizeOfFile);
and i output the contents of "FileContents" into a file at any location(according to my wish) .
What i found is the file contents are displayed properly but as the contents of file are finished i have strange data like "ÌÌÌÌÌÌÌÌÌÌ". please see below-
</body>
</html> //Here finshes the file and after that i have this kind of data as you see below
ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ..and so on until file ends.
and i know its due to memory allocation of char FileContents[200000] ; because the "SizeOfFile" is very small value and after its size i have strange "ÌÌÌÌÌ" and i don't want to see them . What i want is the file which contains only the contents of "FileContents" nothing else. And i can't allocate the memory of FileContents dynalically. because it has to be equal to the "SizeOfFile" which we are getting dynamically using Sizeof(File) .
What to do in this situtaion iin order to get rid of these "ÌÌÌÌÌÌÌÌÌ" values ? Any solution?

You need to initialize the array with zeroes, since its initial contents are undetermined and could contain any value:
// initialize with 0
char FileContents[200000] = {};
You can also set the elements to zero after initialization using std::fill:
// set all elements to 0 after initialization
std::fill(FileContents, FileContents + 200000, 0); // C++03 or C++11
std::fill(std::begin(FileContents), std::end(FileContents), 0); // C++11
When it comes to interpreting char array as strings, these are treated as null terminated strings, meaning the end of the string is marked by the first 0 found.

you need to fill all data with '\0' chars.
So use this:
char FileContents[200000] = {};

doing this worked for me-
char FileContents[200000] ={0};
and do the same after it as i done before.

Related

Dynamically allocated C-style string has more characters than given length?

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.

GetTempPathA function crashes after printing result

I'm trying to get the temporary folder of a user on Windows by using the GetTempPathA function.
LPSTR ptcPath = new CHAR(MAX_PATH);
GetTempPathA(MAX_PATH - 1, ptcPath);
std::cout << "Temporary path : " << ptcPath << std::endl;
So the program outputs correctly the temporary path but crashes right after that (it's part of a big code).
I'm sure the crash comes from GetTempPathA since the program works fine if I comment that line.
It crashes whatever the size I allocate or put instead of MAX_PATH - 1 except for all the values under <size of the path> + 1 that prints gibberish.
I put MAX_PATH - 1 as a value because it solved the problem for someone else on Google Groups.
With
new CHAR(MAX_PATH)
you allocate space for a single CHAR and initialize that one to MAX_PATH. That means your call to GetTempPathA will write out of bounds of that single CHAR element, leading to undefined behavior.
You probably mean
new CHAR[MAX_PATH]
which allocates an array of MAX_PATH elements.
Wow, where should we begin?
the main issue is the expression
new CHAR(MAX_PATH);
this does not allocate an array of characters, but only one, singular character with the value of MAX_PATH.
so in a sense, it as if you've written down
char* c = new char(static_cast<char>(MAX_PATH))
but instead, simply use the fact that std::string has to keep its internal buffer contiguous:
std::string buffer;
buffer.resize(MAX_PATH + 1);
const auto new_size = GetTempPathA(buffer.size(), &buffer[0]); //deal with newsize == 0
buffer.resize(new_size);
anyway, it is worth mentioning that new,new[],delete,delete[] are not used anymore in modern C++. opt for std::vector and std::string for raw memory for IO operations, and std::unique_ptr/std::shared_ptr for all the rest.

Character Constant Array is empty, even though values has been assigned to it [C++]

I am facing problems while assigning string value in a character constant array. Every time when it assigns string value to a particular position of character array. That position value in an array become initialized to empty string, after getting a new value in string variable. I have tried hard to get it out but in vain. Following is the code that I am using:
const char *array[40];
string line="";
ifstream myfile( "text.txt");
if (myfile)
{
int in=0;
while (getline( myfile, line ))
{
array[in]=line.data();
in++;
}
myfile.close();
}
else return;
Now, array variable has all the empty string values. Please let me know how can I do it?
You are accessing the internal data buffer of string object line and let array[in] point to it. When reading the next line, this buffer is either overwritten or may point to a different memory location, such that the previously written array[in] points to a memory that has been overwritten with new content or is invalid at all.
If you want to use a const char*[...] array, copy the buffer first:
array[in]= strdup(line.c_str());
Note further, that line.data() gives you an array but without guarantee of a terminating 0x0 at the end. See documentation of string::data() at cppreference.com

C++ Garbage at the end of file

I have a problem and I dont know how to solve it.
The issue is:
char * ary = new Char[];
ifstream fle;
fle.open(1.txt, ios_base::binary);
fle.seekg(fle.end);
long count = fle.tellg();
fle.seek(fle.beg);
here is the problem:
File 1.txt contains: Hello world!.
when I execute:
ary = new char(count);
fle.read(ary, count);
the ary filled like this: Hello world! #T#^#$#FF(garbage)
The file is ookay nothing inside it only what is above.
Platform: Win 7, VS 2012
Any idea how to solve this issue. (Solved)
(Problem 2)
Now I am facing another problem, the fle.read sometimes read more than the size i gave. For Example if i passed like fle.read(buffer, 1000) it ends in some cases (strlen(buffer) = 1500. How can i solve this?
Regards,
char[]-strings in C are usually null-terminated. They are one byte longer than necessary, and the last byte is set to 0x00. That's necessary because C has no way to tell the length of an array.
When you read binary data from a file, no terminating null-character is read into the string. That means a function like printf which operates on char-arrays of unknown length will output the array and any data which happens to come after it in memory until it encounters a null-character.
Solution: allocate the char[]-buffer one byte longer than the length of the data and set the last byte to 0 manually.
Better solution: Don't use C-style char-arrays. Do it the object-oriented way and use the class std::string to represent strings.
I think your problem is not that your array contains garbage, but that you forgot to put the null-terminator character at the end and your print statement doesn't know when to stop.
Also, you wrote new char(count) instead of new char[count]. In the first case, you only instantiate one char with value count while in the second case you create a buffer of count characters.
Try this:
ary = new char[count+1];
fle.read(ary, count);
ary[count] = '\0';
Most of the other answers miss a very important point:
When you do ary = new char(count); you allocate A SINGLE CHARACTER initialized with a symbol with ASCII code count.
You should write this: ary = new char[count + 1];
Well, the most obvious problem is that you are allocating using
new char(count), which allocates a single char, initialized
with count. What you were probably trying to do would be new
char[count]. What you really need is:
std::vector<char> arr( count );
fle.read( &arr[0], count );
Or maybe count + 1 in the allocation, if you want a trailing
'\0' in the buffer.
EDIT:
Since you're still having problems: fle.read will never read
more than requested. What does fle.gcount() return after the
read?
If you do:
std::vector<char> arr( count );
fle.read( &arr[0], count );
arr.resize( fle.gcount() );
you should have a vector with exactly the number of char that
you have read. If you want them as a string, you can construct
one from arr.begin(), arr.end(), or even use std::string
instead of std::vector<char> to begin with.
If you need a '\0' terminated string (for interface with
legacy software), then just create your vector with a size of
count + 1, instead of count, and &arr[0] will be your
'\0' string.
Do not try to use new char[count] here. It's very difficult
to do so correctly. (For example, it will require a try block
and a catch.)
We have to guess a little here, but most likely this comes down to an issue with your debugging. The buffer is filled correctly, but you inspect its contents incorrectly.
Now, ary is declared as char* and I suspect that when you attempt to inspect the contents of ary you use some printing method that expects a null-terminated array. But you did not null-terminate the array. And so you have a buffer overrun.
If you had only printed count characters, then you would not have overrun. Nor would you if you had null-terminated the array, not forgetting to allocate an extra character for the null terminator.
Instead of using raw arrays and new, it would make much more sense to read the buffer into std::string. You should be trying to avoid null-terminated strings as much as possible. You use those when performing interop with non-C++ libraries.
You're reading count characters for a file, you have to allocate one extra character to provide for the string terminator (\0).
ary = new char[count + 1];
ary[count] = '\0';
Try this
ary = new char[count + 1];
fle.read(ary,count);
ary[count] = '\0';
The terminating null character was missing - its not in the file, you have to add it afterwards

C++ char array move null terminator properly?

Hi my problem is kind of difficult to explain so I'll just post my code section here and explain the problem with an example.
This code here has a big and a small array where the big array gets split up in small parts, is stored in the small array and the small array is outputting its content on the screen. Afterwards I free the allocated memory of the small array and initialize it again with the next part of the big array:
//this code is in a loop that runs until all of the big array has been copied
char* splitArray = new char[50];
strncpy(splitArray, bigArray+startPoint, 50); //startPoint is calculated with every loop run, it marks the next point in the array for copying
//output of splitArray on the screen here
delete splitArray;
//repeat loop here
now my problem is that the outputted string has everytime some random symbols at the end. for example "some_characters_here...last_char_hereRANDOM_CHARS_HERE".
after looking deeper into it I found out that splitArray actually doesnt have a size of 50 but of 64 with the null terminator at 64.
so when I copy from bigArray into splitArray then there are still the 14 random characters left after the real string and of course I dont want to output them.
A simple solution would be to manually set the null terminator in the splitArray at [50] but then the program fails to delete the array again.
Can anybody help me find a solution for this? Preferably with some example code, thanks.
How does the program "fail to delete the array again" if you just set splitArray[49] = 0? Don't forget, an array of length 50 is indexed from 0 through 49. splitArray[50] = 0 is writing to memory outside that allocated for splitArray, with all the consequences that entails.
When you allocate memory for the splitArray the memory is not filled with NULL characters, you need to explictly do it. Because of this your string is not properly NULL terminated. To do this you can do char* splitArray = new char[51](); to initialize with NULL character at the time of allocation itself (note that I am allocating 51 chars to have the extra NULL character at the end). . Also note that you need to do delete[] splitArray; and not delete splitArray;.
The function strncpy has the disadvantage that it doesn't terminate the destination string, if the source string contains more than 50 chars. Seems like it does in your case!
If this really is C++, you can do it with std::string splitArray(bigArray+startPoint, 50).
I see a couple of problems with your code:
If you allocate by using new [], you need to free with delete [] (not delete)
Why are you using freestore anyway? From what I can see you might as well use local array.
If you want to store 50 characters in an array, you need 51 for the terminating null character.
You wanted some code:
while(/* condition */)
{
// your logic
char splitArray[51];
strncpy(splitArray, bigArray+startPoint, 50);
splitArray[50] = '\0';
// do stuff with splitArray
// no delete
}
Just doing this will be sufficient:
char* splitArray = new char[50 + 1];
strncpy(splitArray, bigArray+startPoint, 50);
splitArray[50] = '\0';
I'd really question why you're doing this anyway though. This is much cleaner:
std::string split(bigArray+startPoint, 50);
it still does the copy, but handles (de)allocation and termination for you. You can get the underlying character pointer like so:
char const *s = split.c_str();
it'll be correctly nul-terminated, and have the same lifetime as the string object (ie, you don't need to free or delete it).
NB. I haven't changed your original code, but losing the magic integer literals would also be a good idea.