Я написал простую консольную программу для тестирования некоторых ключевых классов в библиотеке, которую я строю.Теперь код собирается правильно, без ошибок.Но после выполнения кода я обнаружил, что приложение перестает работать после вызова метода Index в определенной точке кода.Я попытался отладить несколько разных способов, чтобы получить больше информации о проблеме, но информация, которую я собрал, мне не помогла.Может быть, это поможет кому-то еще, кто знает, что я не делаю (или делаю неправильно).
Вот содержимое пространства имен Util;
template<typename var>
class VectorNode
{
public:
VectorNode(var value, VectorNode<var>* next = NULL, VectorNode<var>* prev = NULL)
{
data = value;
t_next = next;
t_prev = prev;
}
~VectorNode()
{
if (t_next != NULL)
delete t_next;
}
virtual VectorNode<var>* Next(){ return t_next; } // get the next node in line
virtual void Next(VectorNode<var>* newNode){ t_next = newNode; } // set the next node in line
virtual VectorNode<var>* Prev(){ return t_prev; }// get the previous node in line
virtual void Prev(VectorNode<var>* newNode){ t_prev = newNode; } // set the previous node in line
virtual var Value(){ return data; } // get the node's value
private:
var data;
VectorNode<var>* t_next;
VectorNode<var>* t_prev;
};
template<typename var>
class Vector
{
public:
Vector()
{
tailNode = new VectorNode<var>(*(new var));
headNode = new VectorNode<var>(*(new var), tailNode);
tailNode->Prev(headNode);
size = new int;
*size = 0;
}
~Vector()
{
delete headNode;
delete size;
}
int Size(){ return *size; } // get the size of a vector
void Add(var toAdd, int index = 0) //
{
VectorNode<var>* lastNode;
if (index > (*size))
index = *size;
if (index < 1) // add to the end of the vector
{
lastNode = tailNode;
}
else
{
int i;
if (index <= (*size / 2)) // if the index is less than half the size, iterate forwards
{
lastNode = headNode;
for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
}
else // otherwise, iterate backwards
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev(); }
}
}
VectorNode<var>* temp = lastNode->Prev();
VectorNode<var>* newNode = new VectorNode<var>(toAdd, lastNode, temp);
lastNode->Prev(newNode);
temp->Next(newNode);
*size = *size + 1;
}
void Remove(int index) // remove an index
{
VectorNode<var>* toRemove;
VectorNode<var>* lastNode;
int i;
if ((index > *size) || (index < 1)) // if not in the domain...
index = *size;
if (index <= (*size / 2)) // iterate forwards
{
lastNode = headNode;
for (i = 1; i < index+2; i++){ lastNode = lastNode->Next(); }
}
else // iterate backwards
{
lastNode = tailNode;
for (i = *size; i > index; i--){ lastNode = lastNode->Prev(); }
}
toRemove = lastNode->Prev();
VectorNode<var>* temp = toRemove->Prev();
temp->Next(lastNode);
lastNode->Prev(temp);
delete toRemove;
*size = *size - 1;
}
var Index(int index) // get the value of a node
{
VectorNode<var>* lastNode;
int i;
if (index <= (*size / 2)) // iterate forwards
{
lastNode = headNode;
for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
}
else // iterate backwards
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();}
}
return lastNode->Value();
}
private:
int* size;
VectorNode<var>* tailNode; // the head and tail nodes are placeholders, to keep the list inside its boundaries
VectorNode<var>* headNode;
};
Если вы не хотитепрочитав это, я пометил каждый метод комментарием, объясняя его общую цель.Кроме того, я попытался добавить небольшое объяснение некоторых своих блоков кода.
И вот функция ввода и включения;
<pre>#include "iostream"</p>
<pre>#include "stdlib.h" // this has nothing in it that's being used</pre>
<pre>#include "testhead.h" // the location of the Util namespace</pre>
<p>int main()
{
using namespace Util;</p>
<pre><code>Vector<int>* x = new Vector<int>();
x->Add(42);
x->Add(24);
x->Add(12);
x->Add(21);
std::cout << "Listing Indices\n";
for (int i = 1; i <= x->Size(); i++)
{
std::cout << i << "\t" << x->Index(i) << "\n";
}
std::cout << "Size(pre-removal):\t" << x->Size() << "\n";
x->Remove(2);
std::cout << "Size(post-removal):\t" << x->Size() << "\n";
std::cout << "Listing Indices\n";
std::cout << 3 << "\t" << x->Index(3) << "\n";
for (int i = 1; i <= x->Size(); i++)
{
std::cout << i << "\t" << x->Index(i) << "\n";
}
system("Pause");
}
Хорошо, результаты, которые я получил, где это.Перед использованием метода Remove доступ к любому индексу можно получить из класса Vector.Но, после использования метода remove, независимо от того, какой индекс удален, доступ к индексу выше единицы невозможен.За исключением случая, когда мы удаляем первый индекс, тогда никакие индексы не могут быть доступны.Я попытался пошагово пройти по коду, но он привел меня к этой строке кода в методе index;
else
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();} // error occurs after running this line
}
Теперь, когда я смог понять, что метод Remove вызывает проблему, я пошелназад и получил некоторый вывод об этом.Я должен был выполнить следующую строку до завершения выполнения, дважды.Один раз перед удалением toRemove и еще раз после его удаления.
std::cout << (lastNode->Prev() == temp) << "\t" << (temp->Next() == lastNode) << "\n";
Перед удалением он печатает 1 дважды, указывая, что сравнение было истинным.Но во второй раз я вызываю метод Prev и Next, и программа зависает.Я знаю, что это потому, что я освободил место в памяти, но сравнение показывает, что все ссылки с других узлов на удаленный мной узел исчезли.Теперь мой конкретный вопрос: почему именно это вызывается, и как я могу это исправить?Я немного знаю об управлении памятью в куче, и это не совсем похоже на то, как если бы это вызвало какие-либо проблемы с программой.Итак, я мог бы использовать краткое объяснение того, почему это происходит, если кто-то будет любезен предоставить его.
Если это поможет, я использую IDE Code :: Blocks и компилятор GNU GCC.Также, пожалуйста, скажите мне, если я делаю что-то неправильно, в связи с тем, как я задал вопрос.Я не часто бываю в Stack Overflow и не задаю здесь вопросов.Это лучшее место, где я могу ответить на ваши вопросы.