So, I've made a function that looks like this:
const char **myFunction(char *string)
{
char *bufCopy = new char[strlen(string)];
strcpy(bufCopy,string);
char *tmp = func1(bufCopy);
const char **RetVector = new const char* [6];
RetVector[0] = tmp;
return RetVector;
}
func1 (that is strtok) modified the first argument, so when I delete[] it gives me heap corruption. What could I do?
You must always keep track of the original allocation of your bufCopy, only that one can be deleted. tmp probably only points to part of it (inside the buffer somewhere), so you can't delete it.
Related
I tried dataPoolBuffer = realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize)); already, but Xcode reports:assigning to 'char *' from imcompatible type 'void'.
I create a class:
class solutionBuffer{
private:
char * dataPoolBuffer;
char * consumerBuffer;
char * flagBuffer;
int dataPoolSize;
int consumerBufferSize;
mutex safe;
public:
solutionBuffer(){
safe.lock();
dataPoolSize = 0;
consumerBufferSize = 0;
dataPoolBuffer = (char*)malloc(sizeof(char)*1);
consumerBuffer = (char*)malloc(sizeof(char)*1);
flagBuffer = (char*)malloc(sizeof(char)*1);
}
int add(char* data, int length)
{
dataPoolSize += length;
realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
realloc(flagBuffer, sizeof(char)*(dataPoolSize));
memcpy(dataPoolBuffer + dataPoolSize - length, data, sizeof(char)*(length));
return 0;
}
~solutionBuffer(){
printf("%d",strlen(dataPoolBuffer));
free(dataPoolBuffer);
free(consumerBuffer);
free(flagBuffer);
safe.unlock();
}
};
Every time when we call .add function, it will realloc memory for the variable. However, when I do that in main():
char data[] = "0123456789";
char data2[] = "01234567890123456789";
solutionBuffer buffer;
buffer.add(data, 10);
buffer.add(data2, 20);
The xoce shows:pointer being freed was not allocated in ~solutionBuffer() when it was trying to free dataPoolBuffer .
Why it does like that? How to fix that ?
According to the documentation,
realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
reallocates dataPoolBuffer, but doesn't change where dataPoolBuffer points. So odds are pretty good that dataPoolBuffer is now pointing to invalid memory.
dataPoolBuffer = (char*)realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
will do you what you want, but rethink how you are doing this. You're setting yourself up for a lot of pain. Your class violates The Rule of Three, for one thing. std::vector will handle all of container resizing and memory management for you with no muss and no fuss.
When you call realloc(), you need to assign the result back to the pointer variable. realloc() often needs to move the memory to a new location, and it returns that location. Your code leaves the variable pointing to the old location, and you get undefined behavior when you try to use it after that.
So it should be:
dataPoolBuffer = (char*)realloc(dataPoolBuffer, sizeof(char)*(dataPoolSize));
flagBuffer = (char*)realloc(flagBuffer, sizeof(char)*(dataPoolSize));
Say I have this:
int x;
int x = (State Determined By Program);
const char * pArray[(const int)x]; // ??
How would I initialize pArray before using it?
Because the initial size of the Array is determined by user input
Thanks!
Size of dynamically created array on the stack must be known at compile time.
You can either use new:
const char* pArray = new char[x];
...
delete[] pArray;
or better to use std::vector instead (no need to do memory management manually):
vector<char> pArray;
...
pArray.resize(x);
You cannot initialize an array at compile-time if you are determining the size at run-time.
But depending on what you are trying to do, a non-const pointer to const data may provide you with what you're going for.
const char * pArray = new const char[determine_size()];
A more complete example:
int determine_size()
{
return 5;
}
const char * const allocate_a( int size )
{
char * data = new char[size];
for( int i=0; i<size; ++i )
data[i] = 'a';
return data;
}
int main()
{
const char * const pArray = allocate_a(determine_size());
//const char * const pArray = new char[determine_size()];
pArray[0] = 'b'; // compile error: read-only variable is not assignable
pArray = 0 ; // compile error: read-only variable is not assignable
delete[] pArray;
return 0;
}
I do agree with others that a std::vector is probably more what you're looking for. If you want it to behave more like your const array, you can assign it to a const reference.
#include <vector>
int main()
{
std::vector<char> data;
data.resize(5);
const std::vector<char> & pArray = data;
pArray[0] = 'b'; // compile error: read-only variable is not assignable
}
The example you provided attempts to build the array on the stack.
const char pArray[x];
However, you cannot dynamically create objects on the stack. These types of items must be known at compile time. If this is a variable based on user input then you must create the array in heap memory with the new keyword.
const char* pArray = new char[x];
However, not all items need to be created on the heap. Heap allocation is normally a lot slower then stack allocation. If you want to keep your array on the stack you could always use block based initialization.
#define MAX_ITEMS 100
const char pArray[MAX_ITEMS]
It should be noted that the second option is wasteful. Because you can not dynamically resize this array you must allocate a large enough chunk to hold the maximum number of items your program could create.
Finally, you can always use data structures provide by C++. std::vector is such a class. It provides you a good level of abstraction and item are stored in contingent memory like an array. As noted by one of the other answers you should use the resize option once you know the final size of your vector.
std::vector<char> pArray;
pArray.resize(X);
The reason for this is every time you add an element to a vector, if it no longer has enough room to grow, it has to relocate all items so they can exist next to one another. Using the resize method helps prevent vector from having to grow as you add items.
int nSize;
QString str;
char *p = new char[nSize];
p = str.toLocal8bit.data();
delete[] p;
I got a debug error when I tried to delete a char array in Xcode 5.0.2 but this char array is successfully deleted in Xcode 3.0.2.
If it's deleted successfully anywhere, that's a bug.
char* p = new char[nSize];
So far so good. p is a char array.
p = str.toLocal8bit.data();
p now points to (presumably) some underlying data from str.toLocal8bit. You now have no way to reference the memory you just allocated.
delete[] p;
You've now deleted some other object's memory.
The line
p = str.toLocal8bit.data();
overwrites the pointer that you got from new. When you delete p you're deleting memory you don't control.
If you actually need a copy of the string data, you can use memcpy or strcpy to copy from the string to your array (instead of assigning).
If you don't actually need a copy, you could do:
const char* p = str.toLocal8bit.data();
I'm building my own string class in c++ 11 and I have a memory problem.
in main:
MyString str1; //Works ok, constructor creates empty char array.
const char* pointer1 = str1.c_str(); //Return the pointer to the array.
str1.Reserve(5);
// Now, when I use the Reverse method in string1, Pointer1 is
// pointing to the old memory address.
How to I change the array data in str1, but to the memory address?
With aother words, How do I fix this so that:
pointer1 == str1.c_str();
Reserve method:
void reserve(int res)
{
capacity = NewSize(size + res,0 , capacity); //Method to find the best cap.
char* oldData = data;
data = new char[capacity];
memcpy(data, oldData, capacity);
oldData = data;
//delete[] data;
data[(size)] = '\0';
}
This returns all the right data, but when I do "oldData = data", the memory address is lost.
I appreciate all help, thanks!
I think what you are asking is if there is a way to get a return value from your string class which will always point to the current string array. There are a number of ways to do this but generally this indicates bad design/implementation.
The more normal way to do this would be to advise API users that the result of c_str() is invalidated by any subsequent modifications to the object: don't keep the pointer, just call c_str() again.
Two obvious options are: a) a pointer to the pointer, very dangerous because now someone outside your class can tweak it, b) provide a wrapper class which encapsulates a pointer-to-pointer without allowing modifications.
template<typename T>
struct ReadOnlyPointer {
T* m_ptr;
... operator * ...
... operator -> ...
... operator T ...
};
ReadOnlyPointer<const char*> pointer = str1.pointer();
There also appear to be at least a couple of issues with your "reserve" function.
You push a '\0' at data[0] even though size might be zero.
MyString a;
a.reserve(0); // crash? you wrote to the first byte of a zero length array.
After copying the data from oldData to data, for some reason you assign the value of 'data' to 'oldData' and then never use 'oldData' again - this is a memory leak.
Your memcpy uses 'capacity' instead of 'size' so it may be over-copying.
Consider instead:
// ensure we have an additional 'res' bytes.
// caution: unlike stl and boost reserve, these are
// additional bytes, not total bytes.
void reserve(int res)
{
int newCapacity = NewSize(m_size + res, 0, m_capacity); //Method to find the best cap.
if(newCapacity <= m_capacity)
return;
char* newData = new char[newCapacity];
memcpy(newData, m_data, m_size);
delete[] m_data; // release the old allocation
m_data = newData;
m_capacity = newCapacity;
}
The extra data[(size)] = '\0'; could be the cause of your string becoming truncated if you are not changing the value of size elsewhere in your code.
Test code:
void modify_it(char * mystuff)
{
//last element is null i presume for c style strings here.
char test[7] = "123456";
//when i do this i thought i should be able to gain access to this
//bit of memory when the function is destroyed but that does not
//seem to be the case.
//static char test[] = "123123";
//this is also creating memory on stack and not the heap i reckon
//and gets destroyed once the function is done with.
//char * test = new char[7];
//this does the job as long as memory for mystuff has been
//allocated outside the function.
strcpy_s(mystuff,7,test);
//this does not work. I know with c style strings you can't just do
//string assignments they have to be actually copied. in this case
//I was using this in conjunction with static char test thinking
//by having it as static the memory would not get destroyed and i can
//then simply point mystuff to test and be done with it. i would later
//have address the memory cleanup in the main function.
//but anyway this never worked.
mystuff = test;
}
int main(void)
{
//allocate memory on heap where the pointer will point
char * mystuff = new char [7];
modify_it(mystuff);
std::string test_case(mystuff);
//this is the only way i know how to use cout by making it into a c++ string.
std::cout<<test_case.c_str();
delete [] mystuff;
return 0;
}
In the case of a static array in the function why would it not work?
In the case when I allocated memory using new in the function does it get created on the stack or heap?
In the case when I have a string which needs to be copied into a char * form. everything I see usually requires const char* instead of just char*.
I know I could use a reference to take care of this easily. Or char ** to send in the pointer and do it that way. But I just wanted to know if I could do it with just char *. Anyway your thoughts and comments plus any examples would be very helpful.
char * mystuff = new char [7];
delete mystuff;
delete mystuff is causing undefined behavior. You must delete[] what you new[].
The line mystuff = test; causes the variable mystuff to contain the address of the test array. However, this assignment is local to the function. The caller never sees the modified value of mystuff. This is generally true for C/C++: function parameters are passed by value, and local modifications to that value are invisible outside of the function. The only exception to this is if you use the & operator in the parameter list in C++, which causes the parameter to be passed by reference. Like so:
void modify_it(char* &str) { /* ... */ }
However, if you do this, your program still won't work correctly, and will probably crash. That's because the address of test is stack memory, and that memory will be overwritten when modify_it returns. You'll be giving the caller the address of invalid stack memory, which can only lead to bad things. The correct thing to do is one of the following:
/* function allocates, caller frees */
void modify_it(char* &str) {
str = new char[7]; // allocate enough memory for string
memcpy(str, 7, test);
}
Or this:
/* caller allocates and frees */
void modify_it(char* str, size_t str_len) {
if (str_len < 7) { /* report an error. caller didn't allocate enough space. */ }
memcpy(str, 7, test);
}