I have a little problem which occurs after trying to execute function delete_all()
. Any idea why Visual Studio is throwing me an error:
Invalid address specified to RtlValidateHeap, instruction __debugbreak() or something similar
Everything works perfect until I want to execute this function.
#include <iostream>
using namespace std;
struct node {
string name = "n1";
node* prev = NULL;
node* next = NULL;
};
node* add(node* first, string name) {
if (first == NULL) {
return NULL;
}
node* nowy = new node;
if (first->next == NULL) {
nowy->prev = first;
first->next = nowy;
}
else {
while (first->next != NULL) {
first = first->next;
}
nowy->prev = first;
first->next = nowy;
}
nowy->name = name;
return nowy;
}
void writeout(node* first) {
if (first == NULL) cout << "first = NULL";
while (first->next != NULL) {
cout << first->name;
cout << "\n";
first = first->next;
}
if (first->next == NULL) {
cout << first->name;
cout << "\n";
}
}
void delete_all(node* first) {
node* temp;
while (first != NULL) {
temp = first->next;
delete first;
first = temp;
}
}
int main()
{
node n1;
add(&n1, "n2");
add(&n1, "n3");
writeout(&n1);
delete_all(&n1);
}
CodePudding user response:
You declared an object in main()
with automatic storage duration as the first node of the list:
node n1;
You may not destroy it using the delete
operator.
Using your approach of the list implementation, you could define the function delete_all()
the following way:
void delete_all(node* first)
{
if ( first != nullptr )
{
while ( first->next != nullptr )
{
node *temp = first->next;
first->next = temp->next;
delete temp;
}
}
}
But, it will be much better if initially in main()
, you declared a pointer to a node
. In this case, you will need to update the functions.
CodePudding user response:
Your implementation of delete_all()
is fine, but you are passing it a pointer to a node
instance that was not created with new
, so delete
'ing that node is undefined behavior. ALL of your node instances should be created dynamically, including the 1st node.
As such, your add()
function should be updated to not blindly return without creating a new node
instance if first
is initially NULL
. You should instead update the caller's node*
pointer to point at the new node
that was created.
Also, writout()
has undefined behavior if first
is NULL
, because you are unconditionally accessing first->next
whether first
is NULL
or not.
With that said, try something more like this instead:
#include <iostream>
using namespace std;
struct node {
string name = "n1";
node* prev = nullptr;
node* next = nullptr;
};
node* add(node* &first, string name) {
if (!first) {
first = new node{name};
return first;
}
else {
node *prev = first;
while (prev->next) {
prev = prev->next;
}
prev->next = new node{name, prev};
return prev->next;
}
}
/* alternatively:
node* add(node* &first, string name) {
node **nowy = &first, *prev = nullptr;
while (*nowy) {
prev = *nowy;
nowy = &(prev->next);
}
*nowy = new node{name, prev};
return *nowy;
}
*/
void writeout(node* first) {
if (!first) {
cout << "first = NULL";
}
else {
do {
cout << first->name;
first = first->next;
if (first) cout << '\n';
}
while (first);
}
}
void delete_all(node* first) {
node* temp;
while (first) {
temp = first->next;
delete first;
first = temp;
}
}
int main()
{
node* n1 = nullptr;
add(n1, "n2");
add(n1, "n3");
writeout(n1);
delete_all(n1);
}
Alternatively:
...
node* add(node* first, string name) {
if (!first) {
return new node{name};
}
else {
while (first->next) {
first = first->next;
}
first->next = new node{name, first};
return first->next;
}
}
/* alternatively
node* add(node* first, string name) {
// same as node** further above ...
}
*/
...
int main()
{
node* n1 = add(nullptr, "n2");
add(n1, "n3");
...
delete_all(n1);
}