Я тестирую класс, представляющий структуру данных динамического массива, которую я сделал для себя в качестве практики с языком, но столкнулся с проблемой, когда деструктор вызывается дважды, что вызывает ошибку повреждения кучи.
До сих пор я пытался закомментировать некоторые удаляемые слова. Однако это приводит к неопределенному поведению.
#include <iostream>
#include "windows.h"
#include <vector>
template<typename T> class Spider {
private:
T** pointer;
int maxSize;
int lengthFilled;
public:
//default constructor
Spider()
{
pointer = new T * [1];
maxSize = 1;
lengthFilled = 0;
}
//destructor
~Spider()
{
for (int i = 0; i < lengthFilled; i++)
{
pop();
}
delete[] pointer;
}
//Pushes an object in
void push(T thing)
{
if (lengthFilled == maxSize)
{
increaseSize();
}
T* thinggummy = &thing;
//then save its pointer in the functional array
pointer[lengthFilled] = thinggummy;
lengthFilled++;
}
//pops the array
void pop()
{
delete pointer[lengthFilled-1];
setSize(lengthFilled - 1);
lengthFilled--;
}
}
int main()
{
Spider<Spider<int>> test((long long)1);
for (int i = 0; i < 2; i++)
{
test.push(Spider<int>());
test.get(i).push(2);//this is implemented in the actual code, just omitted here
std::cout << test.get(i).get(0);
std::cout << "push complete\n";
}
system("pause");
return 0;
}
Ожидаемые результаты этой программы должны быть:
2
push complete
2
push complete
Нажмите любую клавишу для продолжения...
Вместо этого я получаю код критической ошибки в журнале отладки «Обнаружена критическая ошибка c0000374».
@StoryTeller В основном это отвечает на вопрос ОП.
@πάνταῥεῖ - Это не так. OP берет локальный адрес и сохраняет его. Они еще не достигли правила 3.
T* thinggummy = &thing
. Вы берете адрес переменной стека и исчезнете, как только ваш push
завершит свое выполнение. И может случиться бум!!, как только вы разыменуете thinggummy
@WhiteSword - вы должны публиковать ответы в (теперь вновь открытом) разделе ответов.
@XnossisX Как ваш код вообще компилируется? Я полагаю, вы пытались предоставить минималистичный код с синтаксисом и другими ошибками, верно?
Да, я предоставил версию кода, которая была единственной частью, необходимой для обнаружения проблемы.
Здесь есть две проблемы:
T *thinggummy = &thing
. Это вызовет проблемы, поскольку этот адрес станет недействительным, как только вы покинете область действия (если, возможно, T
не разрешается в ссылочный тип).delete
вещи в массиве pointer
. Однако они не были распределены через new
. Вместо этого они просто адреса чего-то. Итак, вы пытаетесь освободить то, что никогда не выделялось.Спасибо! Нужно ли мне создавать новый T в куче, а затем глубоко копировать содержимое?
Что делать, зависит от того, какой на самом деле тип T
и/или для каких типов должен работать этот класс Spider
. Например, если T
является примитивным типом, то не нужно ничего выделять/освобождать. Если T
является указателем, то, возможно, можно просто сохранить указатель, возможно, вам нужна глубокая копия. В общем, вы, вероятно, захотите полагаться на конструктор копирования и операторы присваивания T
, чтобы делать правильные вещи. Вы можете проверить некоторые учебники/курсы по шаблонам. Такие вещи обычно подробно объясняются там.
@πάνταῥεῖ - Нет, не тот. Неправильный дубликат хуже, чем просто дубликат, оставшийся ошибочно открытым