【问题标题】:C++ adding one line of code after while loop causes an errorC++在while循环后加一行代码会报错
【发布时间】:2017-03-24 23:36:12
【问题描述】:

我已尽我所能寻找解决我特定问题的答案,但不幸的是,我无法找到满足我需求的答案。

我正在用 c++ 为我编写的一种语言编写一个汇编程序。编写汇编程序涉及两个类,这两个类导致了非常难以调试的问题。我的调试技术已经演变为添加和删除输出流命令,如

std::cout << "TEST";

最终会破坏或修复程序。我使用的 IDE 是 Xcode。

我正在处理的两个类是 LinkedList 类和 SymbolTable 类,我将其用作符号解析的哈希表。

LinkedList.h

#include <iostream>
using namespace std;

struct Node{
    string data;
    int address;
    Node* next = nullptr;
};

class LinkedList{
private:
    Node* main_ptr;
    int length;
public:
    LinkedList();

    void insertNode(string, int);
    void deleteNode(string);
    void displayList();

    bool contains(string, int* = nullptr);
    int getLength();

    ~LinkedList();
};

LinkedList.cpp

#include "LinkedList.h"

LinkedList::LinkedList(){
    main_ptr = nullptr;
    length = 0;
}

void LinkedList::insertNode(string data, int address){
    Node* newNode = new Node;
    newNode->data = data;
    newNode->address = address;

    if (!main_ptr){
        main_ptr = newNode;
    } else {
        newNode->next = main_ptr;
        main_ptr = newNode;
    }
    length++;
}

void LinkedList::deleteNode(string data){
    if (main_ptr){
        int current_length = length;
        if (main_ptr->data == data){
            main_ptr = main_ptr->next;
            return;
        }
        Node* q = main_ptr;
        Node* p = q;
        q = q->next;
        while (q){
            if (q->data == data){
                p->next = q->next;
                length--;
                return;
            }
            p = q;
            q = q->next;
        }
        if (current_length == length) cout << "Node was not found" << endl;
    } else {
        cout << "List is empty, cannot delete node!" << endl;
    }
}

void LinkedList::displayList(){
    if (!main_ptr){
        cout << "List is empty!\n";
    } else {
        Node* temp = main_ptr;
        while (temp){
            cout << temp->data;
            temp = temp->next;
        }
        cout << endl;
    }
}

bool LinkedList::contains(string data, int* address){
    if (main_ptr == nullptr) return false;
    else {
        Node* temp = main_ptr;
        while(temp != nullptr){
            if (temp->data == data) {
                address = &(temp->address);
                return true;
            }
            temp = temp->next;
        }
        return false;
    }
}

int LinkedList::getLength(){
    return length;
}

LinkedList::~LinkedList(){
    if (main_ptr){
        Node* q = main_ptr;
        Node* p = q;
        while (q){
            q = q->next;
            delete p;
            p = q;
        }
    }
}

符号表.h

#include "LinkedList.h"
#include <iostream>

class SymbolTable{
private:
    LinkedList table[701];
public:
    SymbolTable();

    void addEntry(string, int);
    void printTable();
    bool contains(string, int*);

    int convertName(string);
};

符号表.cpp

#include "SymbolTable.h"

SymbolTable::SymbolTable(){
}

void SymbolTable::addEntry(string name, int memory){
    int address = convertName(name);
    table[address].insertNode(name, memory);
}

void SymbolTable::printTable(){
    for (int i = 0; i < 701; i++)
        table[i].displayList();
}

bool SymbolTable::contains(string name, int* memory){
    return table[convertName(name)].contains(name, memory);
}

int SymbolTable::convertName(string name){
    int aggregate = 1;
    const char* c_name = name.c_str();
    for (int i = 0; i < name.length(); i++){
        aggregate *= (int)c_name[i];
    }
    return aggregate%701;
}

现在是我的实际问题。以下是主要功能:

#include "Parser.h"
#include "SymbolTable.h"

using namespace std;

int main(int argc, const char * argv[]) {

    ifstream inputFile;
    ofstream outputFile;

    inputFile.open("/Users/Azaldin/Desktop/nand2tetris/projects/06/max/Max.asm");
    outputFile.open("/Users/Azaldin/Desktop/nand2tetris/projects/06/max/Max.hack");

    Parser a(inputFile);
    SymbolTable s;

    int commandType = -1;
    string command;
    int a_position = 16;
    int currentLine = 0;

    while (a.hasMoreCommands()){
        a.advance();
        commandType = a.commandType();
        command = a.symbol();

        if (commandType == 0){
            if (!s.contains(command, nullptr)){
                s.addEntry(command, a_position);
                a_position++;
            }
        }

        if (commandType == 2){
            //cout << command << endl;
            if (!s.contains(command, nullptr)){
                s.addEntry(command, currentLine);
                //cout << command << endl;
            }
        }

        currentLine++;
    }

    string x;  //<<<<<<<<<< ADDING THIS LINE BREAKS THE PROGRAM
    cout << "Hi";

    inputFile.close();
    outputFile.close();

    return 0;
}

在主函数中添加上面指向的行后,程序中断。 调试时,主线程出现如下问题:

线程 1:EXC_BAD_ACCESS(代码 = 1,地址=0x25fbfef80)

导致这个问题的命令链:

  1. if (!s.contains(command, nullptr)){ 来自主函数

  2. return table[convertName(name)].contains(name, memory); 来自 SymbolTable.cpp “包含”函数

  3. if (temp-&gt;data == data) { 来自 LinkedList.cpp “包含”函数

链命令的其余部分导致字符串 class== 运算符,然后导致左侧的 .size() 函数。

谢谢!

【问题讨论】:

  • 最终会破坏或修复程序。 -- 两个词 -- 内存损坏。删除或添加基本上不执行任何操作的代码行表明您正在破坏内存。更改代码以复制错误,然后修复错误。不要误以为通过添加无操作的代码行即可解决问题。
  • 另外,你如何检查convertName(name) 是否在table 数组的范围内?我没有看到任何支票。最好使用std::array&lt;int, 701&gt; table; 而不是一无所知的数组。使用std::array 让您有机会通过调用at() 方法而不是[ ] 来检查边界。另外,为什么要编写自己的链表类而不是使用std::list
  • 顺便说一句在deleteNode你不delete任何Node
  • ... 在contains() 中,您不会更改传递给它的指针adress(仅在本地)。也许你想通过参考传递它
  • 另外,aggregate *= (int)c_name[i]; -- 不能保证这将是一个正数,因为一个字符可能是有符号的,因此给你 -1 及以下的值。因此,您返回 return aggregate%701; 不会返回您预期的结果(数字 >= 0)。

标签: c++ string memory-management exc-bad-access


【解决方案1】:

PaulMcKenzie 的以下评论帮助解决了这个问题:

另外,聚合 *= (int)c_name[i]; -- 不能保证这 将是一个正数,因为一个字符可能是有符号的,因此 给你 -1 及以下的值。因此你的回报 聚合%701;不会返回您所期望的(数字 >= 0).

事实证明,传递给 SymbolTable 类中 convertName 函数的参数之一导致程序损坏了内存。我添加了一个 if 语句来解决问题。

【讨论】:

    猜你喜欢
    • 2014-01-30
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 2019-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多