Нарушение доступа к памяти в C ++ при установке свойства объекта - PullRequest
0 голосов
/ 26 ноября 2010

Возникли проблемы с получением одной части моего кода для работы.Создание элементарного связного списка для изучения указателей.Я думаю, что у меня большая часть отключена, но любые попытки использовать созданную мной функцию (push_back) выдают ошибки доступа к памяти при установке значения для указателя.

Не совсем уверен, что не так, потому что он отлично работаетиспользовать push_front, которые работают почти одинаково.

Есть идеи?= /

КОД:

driver.cpp

#include <string>
#include <iostream>
#include "linklist.h"
#include "node.h"

using namespace std;

// printList function
// Purpose: Prints each node in a list
// Returns: None.
// Pre-Conditions: List must have member nodes.
// Post-Conditions: None.
void printList(linklist);

int main()
{
     linklist grocery;

     grocery.push_front(new node("milk", "1 gallon"));
     grocery.push_front(new node("bread","2 loaves"));
     grocery.push_front(new node("eggs","1 dozen"));
     grocery.push_front(new node("bacon","1 package"));
     cout << "First iteration:" << endl;
     printList(grocery);
     cout << "----------------------" << endl << endl;

     grocery.push_front(new node("hamburger","2 pounds"));
     grocery.push_front(new node("hamburger buns", "1 dozen"));
     cout << "Second iteration:" << endl;
     printList(grocery);
     cout << "----------------------" << endl << endl;

     node* deleteMe = grocery.pop_front();
     delete deleteMe;
     cout << "Third iteration:" << endl;
     printList(grocery);
     cout << "----------------------" << endl << endl;

     grocery.push_back(new node("orange juice","2 cans"));
     grocery.push_back(new node("swiss cheeese","1 pound"));
     cout << "Fourth iteration:" << endl;
     printList(grocery);
     cout << "----------------------" << endl << endl;

     deleteMe = grocery.pop_back();
     delete deleteMe;
     cout << "Fifth iteration:" << endl;
     printList(grocery);
     cout << "----------------------" << endl << endl;

     while (grocery.getNodeCount() != 0)
     {
          deleteMe = grocery.pop_front();
          cout << "Cleaning: " << deleteMe->getDescription() << endl;
          delete deleteMe;
     }

     system("PAUSE");
     return 0;
}

void printList(linklist input)
{
   node* temp = input.getFirst();
   for (int i = 0; i < (input.getNodeCount()); i++)
   {
      cout << temp->getQuantity() << " " << temp->getDescription() << endl;

      temp = temp->getNextNode();
   }
}

node.h

#pragma once
#include <string>

using namespace std;

class node
{
public:
// Default Constructor
// Values, "none", "none", NULL.
node();

// Parameterized Constructor
// nextNode initialized NULL and must be explicitly set.
node(string descriptionInput, string quantityInput);

// getDescription function
// Purpose: Returns node description.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getDescription();

// setDescription function
// Purpose: Sets node description
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setDescription(string);

// getQuantity function
// Purpose: Returns node quantity.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getQuantity();

// setQuantity function
// Purpose: Sets node quantity
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setQuantity(string);

// getNextNode function
// Purpose: Returns pointer to next node in list sequence.
// Returns: node pointer
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
node* getNextNode();

// setNextNode function
// Purpose: Sets pointer to next node in list sequence.
// Returns: None.
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
void setNextNode(node*);
private:
string description;
string quantity;
node* nextNode;
};

node.cpp

#include "node.h"


node::node()
  :description("none"),
  quantity("none"),
  nextNode(NULL)
  {}

node::node(string descriptionInput, string quantityInput)
  :description(descriptionInput),
  quantity(quantityInput),
  nextNode(NULL)
  {}

string node::getDescription()
{
   return description;
}

void node::setDescription(string descriptionInput)
{
   description = descriptionInput;
}

string node::getQuantity()
{
   return quantity;
}

void node::setQuantity(string quantityInput)
{
   quantity = quantityInput;
}

node* node::getNextNode()
{
   return nextNode;
}

void node::setNextNode(node* input)
{
   nextNode = input;
}

linklist.h

#pragma once
#include "node.h"

class linklist
{
public:
// Constructor
// Builds an empty list
linklist();

// push_front function
// Purpose: Takes node pointer. Places that node at beginning of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_front(node*);

// pop_front function
// Purpose: Removes first node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_front();

// getFirst function
// Purpose: Returns node pointer to first node in list
// Returns: node pointer
// Pre-Conditions: List must have a node added.
// Post-Conditions: None.
node* getFirst();

// push_back function
// Purpose: Takes node pointer. Places that node at end of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_back(node*);

// pop_back function
// Purpose: Removes last node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_back();

// getNodeCount function
// Purpose: Returns nodeCount
// Returns: int
// Pre-Conditions: None.
// Post-Conditions: None.
int getNodeCount();
private:
node* firstNode;
node* lastNode;
int nodeCount;
};

linklist.cpp

#include "linklist.h"


linklist::linklist()
    :firstNode(NULL),
    lastNode(NULL),
    nodeCount(0)
{}

void linklist::push_front(node* input)
{
    node* temp = getFirst();

    input->setNextNode(temp);

    firstNode = input;
    nodeCount++;
}

node* linklist::pop_front()
{
    node* temp = getFirst();

    firstNode = temp->getNextNode();

    nodeCount--;
    return temp;
}

node* linklist::getFirst()
{
    return firstNode;
}

void linklist::push_back(node* input)
{
    node* temp = lastNode;

    temp->setNextNode(input);

    lastNode = temp;
    nodeCount++;
}

node* linklist::pop_back()
{
    node* oldLast = lastNode;
    node* temp = firstNode;

    // find second to last node, remove it's pointer
    for (int i = 0; i < (nodeCount - 1); i++)
    {
        temp = temp->getNextNode();
    }
    temp->setNextNode(NULL);

    lastNode = temp;

    nodeCount--;
    return oldLast;
}

int linklist::getNodeCount()
{
    return nodeCount;
}

Ответы [ 4 ]

2 голосов
/ 26 ноября 2010

У вас есть ошибки в методах толчка, потому что, когда вы толкаете вперед, вы не контролируете, является ли этот элемент также последним и похожим, когда вы толкаете в конце.Это приводит к тому, что вы не подключили весь список, потому что начальная часть не знает о конечной части.Я надеюсь, что это понятно.

Также поп-методы неправильны - та же проблема.Вы не контролируете, если список пуст

1 голос
/ 26 ноября 2010

Согласно определению node это односвязный список. (в противном случае вы должны будете также содержать prevNode).

Следовательно - манипулирование «спиной» вашего списка нетривиально. Чтобы вытолкнуть «назад» вашего списка, вам нужно пересечь весь список и определить новый «последний» элемент.

Вы уверены, что делаете это правильно? Включая обработку всех «экстремальных» случаев (например, удаление последнего элемента и т. Д.)?

Было бы неплохо опубликовать код push_back и pop_back.

P.S. Возможно, вы неправильно установили lastNode в push_front и pop_front. Вы можете не заметить этого, если не пытаетесь манипулировать своей «спиной».

Отправьте также код push_front и pop_front.

EDIT

Хорошо, я вижу код. И ошибок много.

void linklist::push_front(node* input)
{
    node* temp = getFirst();

    input->setNextNode(temp);

    firstNode = input;
    nodeCount++;

    // Missing:
    if (!temp)
        lastNode = firstNode;
}


node* linklist::pop_front()
{
    node* temp = getFirst();

    firstNode = temp->getNextNode();

    // Missing:
    if (!firstNode)
        lastNode = 0;

    nodeCount--;
    return temp;
}


void linklist::push_back(node* input)
{
    node* temp = lastNode;

    // instead of
    // temp->setNextNode(input);
    // lastNode = temp;

    // should be:
    if (temp)
        temp->setNextNode(input);
    else
        firstNode = input;

    lastNode = input;

    nodeCount++;
}

node* linklist::pop_back()
{
    node* oldLast = lastNode;

    if (firstNode == lastNode)
    {
        firstNode = 0;
        lastNode = 0;
    } else
    {
        node* temp = firstNode;

        // find second to last node, remove it's pointer
        for (int i = 0; i < (nodeCount - 1); i++)
        {
            temp = temp->getNextNode();
        }
        temp->setNextNode(NULL);

        lastNode = temp;
    }

    nodeCount--;
    return oldLast;
}
1 голос
/ 26 ноября 2010

Похоже, у вас есть одна простая ошибка в вашем push_back:

void linklist::push_back(node* input) 
{ 
   node* temp = lastNode; 

   temp->setNextNode(input); 

   lastNode = temp; //this looks wrong
   nodeCount++; 
} 

Как указано выше, я думаю, вы имели в виду lastNode = input;

p.s. тщательно учтите исключительную безопасность. Нередко поп-подпрограммы не возвращают ничего и вместо этого соединяются с подпрограммой peek () для поддержки нейтральности / безопасности исключений.

1 голос
/ 26 ноября 2010

Ну, когда список пуст, в push_back temp указано NULL. Поэтому temp->setNextNode(input) терпит неудачу. Вы должны различать особый случай пустого списка.

Кстати, если вы разрешаете операции как сзади, так и спереди, возможно, вам нужен двусвязный список? В противном случае вам нужно будет просмотреть весь (потенциально огромный) список, чтобы вытолкнуть последний элемент, поскольку у вас нет «прямой» ссылки на предыдущий элемент.

Кстати, вы работаете с deque, а не со списком.

...