I have this class, with the atribute 'word'
class Node {
char *word;
Inside the Node constructor, I do this asignation:
word = new char[strlen(someword)];
In the destructor of the Node class, I try to delete the contents pointed by word:
delete []word;
I obtain the next message after executing the programs:
"Heap block at 003E4F48 modified at 003E4F51 past requested size of 1"
What am I not doing well?
You have a buffer overflow in your program, somewhere else in code you didn't post. The problem is that you're not allocating enough memory -- you don't leave room for the null terminator at the end of your string. You should change the allocation to this:
word = new char[strlen(someword) + 1]; // +1 for null terminator
...
strcpy(word, someword);
You should be thankful your C runtime caught your error. In most cases, a one byte buffer overflow will result in silent memory corruption and not be detected until much later, if ever.
You should also consider using the std::string class, which automatically manages the memory for you, so you don't have to deal with subtle issues like this.
strlen will return the length of the string but will not account for the null-terminating extra byte. My guess is that you are then copying in a string and appending a null-byte but you did not account for it when you originally allocated the memory. Try changing the code to read:
word = new char[strlen(someword) + 1];
You have a corrupt heap - somewhere else in your code you are writing outside the allocated memory or deleting something you shouldn't be - are you sure you don't mean strlen(someworrd) + 1?. The best solution to this problem is to use a std:;string or a std::vector rather than a dynamic array.
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 am trying to concatenate two char arrays using the function strcat(). However the program crashes.
#include <cstdio>
#include <cstring>
int main() {
const char *file_path = "D:/MyFolder/YetAnotherFolder/test.txt";
const char *file_bk_path = strcat(strdup(file_path), ".bk");
printf("%s\n", file_bk_path);
return 0;
}
The strangest thing to me is that the program indeed produces an output before crashing:
D:/MyFolder/YetAnotherFolder/test.txt.bk
What is the reason for this problem and how it can be fixed?
Error state is reproduced in Windows (MinGW 7.2.0).
strdup is creating new memory for you to hold a duplicate of the string. The memory is only as long as strlen(file_path) + 1. You then try to add an extra 2 characters into memory that you don't own. You will go out of range of the memory created and create some undefined behaviour. It might print because setting the memory and printing the first part could be happening correctly, but it is undefined and anything can happen. Also note, in strdup you need to call free on the memory it creates for you, or you are going to leak some memory.
Here is a much simpler way to do this, use a std::string:
const char *file_path = "D:/MyFolder/YetAnotherFolder/test.txt";
std::string file_bk_path = std::string(file_path) + ".bk";
std::cout << file_bk_path << "\n";
Here is a live example.
If it absolutely needs to be in C-style then you are better off controlling the memory yourself:
const char *file_path = "D:/MyFolder/YetAnotherFolder/test.txt";
const char *bk_string = ".bk";
char *file_bk_path = malloc((strlen(file_path) + strlen(bk_string) + 1)*sizeof(char));
if (!file_bk_path) { exit(1); }
strcpy(file_bk_path, file_path);
strcat(file_bk_path, bk_string);
printf("%s\n", file_bk_path);
free(file_bk_path);
Here is a live example.
As mentioned in the comments and answers, strdup mallocs the length of your path string, plus an extra cell for the string end character '\0'. When you concatenate to this two characters writing after the allocated area.
Following #Ben's comments, I'd like to elucidate some more:
To be clear strcat adds a delimiter, but this is already after the memory you were allocated.
In general unless you specifically hit no-no addresses, the program will probably run fine - in fact this is a common hard to find bug. If for example you allocate some more memory right after that address, you will be deleting said delimiter (so printing the string will read further into the memory.
So in general, you may be OK crash wise. The crash (probably) occurs when the program ends, and the OS cleans up the memory you forgot to free yourself - That extra cell is a memory leak, and will cause the crash. So you do get a full print, and only after a crash.
Of course all of this is undefined behavior, so may depend on the compiler and OS.
This is probably a noob question. I am using Marmalade SDK. If I allocate some memory for a char array dynamically I get an access violation. I cannot figure out what I am doing wrong.
Is this a valid way to use malloc and free?
const char* CClass::caption(int something)
{
...
//char stringPrediction[2000]; // <--- This works
size_t string01_Size = strlen(string01);
size_t string02_Size = strlen(string02);
...
stringX = (char *)malloc(string01_Size + string02_Size + 1); // <- Access violation
strcpy(stringX , string01);
strcat(stringX , " ");
strcat(stringX , string02);
return stringX ;
}
Destructor:
CClass::~CClass(void)
{
free(stringX);
}
Then I use it to set the caption of a label on a Button click event
... OnClick...(...)
{
CClass someObject;
label.setCaption(someObject.caption());
}
After a few clicks I get access violation.
Unhandled exception at 0x1007ECB8 (s3e_simulator_debug.dll) in
s3e_simulator_debug.exe: 0xC0000005: Access violation writing
location 0x0000000C.
EDIT: It seems the problems is:
stringX = (char *)malloc(string01_Size + string02_Size + 1);
I have failed to allocate space for this:
strcat(stringX , " ");
This should be better:
stringX = (char *)malloc(string01_Size + 1 + string02_Size + 1);
1.
You're not testing for the case that malloc fails. The error suggests you're trying to dereference a null pointer - the pointer returned when malloc fails.
2.
It doesn't look like you're accounting for the null-byte terminator when calculating the size of your buffer. Assuming string01_Size and string02_Size are the number of characters not including the null byte, you're overflowing your buffer.
Both actions result in undefined behaviour.
Access violation encountered during call of malloc or free in most cases indicates that the heap is corrupt. Due to, most commonly overrun or double free or free issued on dangling pointer, happened sometime earlier. May be way earlier.
From the posted code it's not possible to deduce, as it effectively starts with the crash.
To deal with it you may try valgrind, app verifier, other runtime tools helping with corruption. For that one particular issue -- for the general you should not be there in the first place, using malloc, the str* function an all the inherited crap from C.
Consistent use of collection classes, String class, etc would prevent too many cases leading to drastic problems.
You've basically spotted the issue: by not allocating for the space you're second strcat will overrun and probably crunch the heap pointers of the next block. Additional things to watch (you're probably be doing this anyway) are to free stringX in CClass::caption() before reallocating so you don't leak. Whatever you really should check that the malloc has not failed before use.
As others have suggested, it may be better to use std::string. You can always convert these to char* if required. Of course, if you do so you should consider that exceptions might be thrown and program accordingly.
I'm writing a C++ program, that stores strings in a string array, when the array is full I resize the array to make space for more items using the code below. But sometimes (not always) it crashes at the "delete[] temp;" line and I don't know why and how to fix it. Please, help.
I have searched a lot but could not find an answer anywhere. When I debug it says "invalid pointer" but how can it be invalid when I stored data there before and did not free it yet?
This is my code:
if(item_cnt >= (arr_size - 1))
{
int oldsize = arr_size;
string * temp;
arr_size *= 2;
temp = arr;
arr = new string [arr_size];
memcpy(arr, temp, oldsize * sizeof(temp));
delete[] temp;
}
Unless you absolutely have to stick with your current approach, I would recommend using a vector to hold your strings. It will manage all the memory for you.
Here's an example:
#include <vector>
#include <string>
int main()
{
std::vector<std::string> arrayOfStrings;
arrayOfStrings.push_back("Hello World!"); // To Add Items
string value = arrayOfString.at(<some index>); // To Retrieve an Item you can also use the [] operator instead of the at method
return 0;
}
The memcpy is at the root of your problem. everyone's said "don't use it", but let me explain exactly why it's a terminally bad idea.
First off, what is a c++ string, and how does it do its magic? It's basically a variable-length array of characters, and it achieves this feat by holding a pointer within each string object that points to the memory allocated to hold those characters. As the string grows or shrinks, that memory gets reallocated. Copy strings properly involves making a 'deep copy' of the contents.
Now, to your code:
arr = new string [arr_size];
This creates an array of empty string objects. Because they're empty, the internal pointers are typically null.
memcpy(arr, temp, oldsize * sizeof(temp));
Here, bad things happen. This isn't actually creating copies of the original strings, it's just overwriting the internal representation. So both the old and the new strings 'point' to the same character data. Now to really screw things up, this happens:
delete[] temp;
We delete thew old strings, but this also frees up the character memory that they were using. So our 'new' copies of these strings are pointing at memory that's actually been freed. We now have a car-crash waiting to happen : The character data could be re-used for anything, and when we try and delete the strings again, the operating system will hopefully spot that you're trying to free memory that hasn't been allocated.
Your array should be really
vector<string>
This is a recommended way of implementing arrays of dynamic size. By using vector you avoid necessity to reallocate/copy stuff manually and avoid problems like the one you have altogether.
Mixing old style and new style memory operations is always a bad idea... here you use memcpy and new/ delete. be aware that delete[] also calls the dtor for each element of the array...
Edit:
ctor --> dtor
hth
Mario
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.