i have two vectors. one is a (1) vector which contains all objects im using and works with that. the other vector is a (2) vector which after a function adds an object from (1) into (2). once this happens i want to remove the object from (1). the problem is that the function i made to remove it takes in a object * obj. the actual object still has pointers pointing to it and i dont want to fully wipe the obj, just remove it from (1). any help would be appreciated.
`
void removeObject(const Object * obj) {
int index;
for (int i = 0; i < size(); i++) {
if (obj == & objectVector[i] ) {
index = i;
}
}
objectVector.erase(objectVector.begin() + index);
}
`
im sure this is the problem because when i dont comment out the line using this function i get a sigtrap error
Related
I am currently programming the ESP32 board in C++ and I am having trouble with my dataContainer class and releasing/allocating memory.
I do use the following DataContainer class (simplyfied):
template <typename Elementtype>
class DataContainer
{
private:
Elementtype **datalist;
int maxsize;
std::size_t currentsize; // How much data is saved in datalist
public:
DataContainer(int maxcapacity);
~DataContainer();
...some methods...
void reset_all_data();
};
And here is the reset_all_data() definition:
/* Deletes all Data of Datacontainer and allocates new memory*/
template <typename Elementtype>
void DataContainer<Elementtype>::reset_all_data()
{
for (int i = 0; i < currentsize; i++)
{
if (datalist[i])
Serial.println(heap_caps_check_integrity_all(true));
delete datalist[i]; <-- Error is triggered here!!!
Serial.println(heap_caps_check_integrity_all(true));
}
delete datalist;
datalist = new Elementtype *[maxsize];
for (int i = 0; i < maxsize; i++) // Declare a memory block of size maxsize (maxsize = 50)
{
datalist[i] = new Elementtype[5];
}
currentsize = 0;
}
As you can see, I have added some integrity checks, but the one before delete datalist (this seems to trigger the error). When I call reset_all_data() from my main.cpp at a certain point in my program the following error is triggered:
CORRUPT HEAP: Bad head at 0x3ffbb0f0. Expected 0xabba1234 got 0x3ffb9a34
assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)
Backtrace:0x40083881:0x3ffb25400x4008e7e5:0x3ffb2560 0x40093d55:0x3ffb2580 0x4009399b:0x3ffb26b0 0x40083d41:0x3ffb26d0
0x40093d85:0x3ffb26f0 0x4014e3f5:0x3ffb2710 0x400d2dc6:0x3ffb2730 0x400d31e3:0x3ffb2750 0x400d9b02:0x3ffb2820
One more thing, the error is only triggered when a certain function is called right before it, even when the whole code inside this function is commented. This is the function's head: void write_data_container_to_file(fs::FS &fs, const char *path, DataContainer<uint16_t> data, const char *RTC_timestamp)thus, the mere call of the function plays an import role here.
Right now I am completely lost - any suggestion/idea is welcome on how to proceed.
EDIT: The dataContainer holds a 2D array of uint16_t.
I finally tracked down the, rather obvious, reason for the HEAP CORRUPTION. In the end I only called delete datalist but it would have been correct to call delete[] datalist after the for loop. The reason is, that within the for loop I delete the pointers pointing to arrays, which represent the "rows" of my allcoated 2D memory. In the end, I also have to delete the pointer, which points to the array holding the pointers I deleted within the for loop.
So I was not paying attention and one should watch out that when it comes to releasing the previously allocated memory, care should be taken if delete or delete[]should be called.
After reading this article, I have some question in mind.
Basically, why we need to store the return value of append() in Go? How is the function actually implemented?
I have tried to replicate (sort of) the mechanism of append in C (which is the first language used to implements the Go language, if I'm not mistaken). I used malloc(), instead of an array as it will not deallocate the slice after the function returns.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct SliceHeader {
int length;
int capacity;
int *zerothElement;
} SliceHeader;
void append(SliceHeader *sh, int element)
{
if (sh->length == sh->capacity) {
// grow capacity size
sh->capacity += 10;
realloc(sh->zerothElement, sh->capacity);
}
sh->zerothElement[sh->length] = element;
sh->length++;
}
SliceHeader * make(int capacity)
{
SliceHeader *sh = (SliceHeader *) malloc(sizeof(sh));
sh->length = 0;
sh->capacity = capacity;
sh->zerothElement = (int *) malloc(capacity * sizeof(int));
return sh;
}
int main()
{
SliceHeader *sh = make(3);
append(sh, 5);
append(sh, 10);
append(sh, 15);
append(sh, 20); // exceed the original capacity, should reallocate
for (int i = 0; i < sh->length; i++) {
printf("%d\n", *((sh->zerothElement)+i) );
}
free(sh->zerothElement);
free(sh);
return 0;
}
(I omit NULLs checking to show only the relevant part to the main question).
If I'm using this code, I can use append() without the need to store its return value and no needs to create a new slice header.
So how is the implementation of append() function in Golang that makes it needs to store a new slice header? Even if the zerothElement uses an array, doesn't it means that it will need to change the array only instead of the whole slice header?
What am I missing here?
Thanks :)
Basically, why we need to store the return value of append() in Go?
You only need to store this value if you intend to use the slice with the appended value.
How is the function actually implemented?
Go is open source, just consult the source code. (Btw: This is uninteresting.)
ALL,
I have a class defined that just holds the data (different types of data). I also have std::vector that holds a pointers to objects of this class.
Something like this:
class Foo
{
};
class Bar
{
private:
std::vector<Foo *> m_fooVector;
};
At one point of time in my program I want to remove an element from this vector. And so I write following:
for (std::vector<Foo *>::iterator it = m_fooVector.begin(); it <= m_fooVector.end(); )
{
if( checking it condition is true )
{
delete (*it);
(*it) = NULL;
m_fooVector.erase( it );
}
}
The problem is that the erase operation fails. When I open the debugger I still see this element inside the vector and when the program finishes it crashes because the element is half way here.
In another function I am trying to remove the simple std::wstring from the vector and everything works fine - string is removed and the size of the vector decreased.
What could be the problem for such behavior? I could of course try to check the erase function in MSVC standard library, but I don't even know where to start.
TIA!!!
Your loop is incorrect:
for (std::vector<Foo *>::iterator it = m_fooVector.begin(); it != m_fooVector.end(); )
{
if (/*checking it condition is true*/)
{
delete *it;
// *it = NULL; // Not needed
it = m_fooVector.erase(it);
} else {
++it;
}
}
Traditional way is erase-remove idiom, but as you have to call delete first (smart pointer would avoid this issue), you might use std::partition instead of std::remove:
auto it = std::partition(m_fooVector.begin(), m_fooVector.end(), ShouldBeKeptFunc);
for (std::vector<Foo *>::iterator it = m_fooVector.begin(); it != m_fooVector.end(); ++it) {
delete *it;
}
m_fooVector.erase(it, m_fooVector.end());
Actually, I am confronted with a code base and have a questions concerning the std::vector concerning stack and heap.
Somewhere in a member function I encounter some code similar to this:
Member declaration:
//member variable in DataHelper class
std::vector<Data::Point> mDataPoints;
Member function:
void DataHelper::LoadData(int nPoints)
{
//mDataPoints is a member variable
mDataPoints.reserve(nPoints);
for (UINT i = 0; i < nPoints; i++)
{
Data::Point point; //some data class
point.X = 1; //dummy values
point.Y = 2;
point.Z = 3;
mDataPoints.push_back(point);
}
}
So the Data::Points are stored in the vector for later use.
I thought that the Data::Point point; is allocated on the stack and that it's storage for later use in this sense will lead to errors. Is this right?
In fact, when you do a push_pack in a std::vector, you copy the data points. So, you will have 2 identical instances, one in the heap and the other one in the vector.
You have to make sure that your Data::Point implements a copy constructor if needed (for instance, if contains pointers).
I have an object with large number of similar fields (like more than 10 of them) and I have to assign them values from an array of variable length. The solution would be either a huge nested bunch of ifs based on checking length of array each time and assigning each field
OR
a chain of ifs checking on whether the length is out of bounds and assigning each time after that check.
Both seem to be repetitive. Is there a better solution ?
If you language has switch/case with fallthrough, you could do it like this:
switch(array.length){
case 15: field14 = array[14];
case 14: field13 = array[13];
case 13: field12 = array[12];
// etc.
case 1: field0 = array[0];
case 0: break;
default: throw Exception("array too long!");
}
for (int i = 0; i < fieldCount; i++)
fields[i].value = array[i];
That is to say, maintain an array of fields that corresponds to your array of values.
If your language supports delegates, anonymous functions, that sort of thing, you can use those to clean it up. For example, in C# you could write this:
string[] values = GetValues();
SomeObject result = new SomeObject();
Apply(values, 0, v => result.ID = v);
Apply(values, 1, v => result.FirstName = v);
Apply(values, 2, v => result.LastName = v);
// etc.
The apply method would look like:
void Apply(string[] values, int index, Action<string> action)
{
if (index < values.Length)
action(values[index]);
}
This is obviously language-dependent, but something to think about regardless.
Another very simple option that we might be overlooking is, if you are actually trying to initialize an object from this value array (as opposed to update an existing object), to just accept the default values if the array isn't large enough.
C# example:
void CreateMyObject(object[] values)
{
MyObject o = new MyObject();
o.ID = GetValueOrDefault<int>(values, 0);
o.FirstName = GetValueOrDefault<string>(values, 0);
o.LastName = GetValueOrDefault<string>(values, 0);
// etc.
}
void GetValueOrDefault<T>(object[] values, int index)
{
if (index < values.Length)
return (T)values[index];
return default(T);
}
Sometimes the dumb solution is the smartest choice.
If your fields are declared in the same order of the array's elements, you could use reflection (if available in your language) to set these values. Here is an example of how you could do it in Java:
// obj is your object, values is the array of values
Field[] fields = obj.getClass().getFields();
for (int i = 0; i < fields.length && i < values.length; ++i) {
fields[i].set(obj, values[i]);
}