C++ 程序 运行 在 VS 上流畅但在 Linux Mint 上不流畅

C++ program running smoothly on VS but not on Linux Mint

出于某种原因,当我 运行 我的 C++ 程序在 VS 上编译时 运行 顺利,当我试图 运行 它在 Linux Mint 终端上时它确实编译没有任何错误,但我没有得到任何 feedback/printing 到终端......它只是卡住了 - 所以我什至无法猜测问题出在哪里。有什么建议吗?

说到Linux我真的是菜鸟... 我的程序包含 2 个 cpp class 文件、2 个头文件(每个头文件对应一个 class)和一个 main.cpp 文件,我试图 运行 像这样:
g++ *.cpp -o myprog
./myprog

它确实创建了一个 myprog 文件 - 但是当我 运行 它没有任何反应,就像我说的那样。

我的代码:

btree.h

#include <iostream>
#ifndef _BTREE_H_
#define _BTREE_H_
class LinkedList;

struct node
{
    int key_value;
    node *left;
    node *right;
};
class btree
{
    friend class LinkedList;
public:
    
    // Default constructor
    btree();
    ~btree();
    // Copy Constructor by list
    btree(LinkedList &list);
    // Copy Constructor by tree
    btree(btree & bt);
    // assignment operator from linked list
    btree & operator=(const LinkedList & ls);
    // assignment operator from tree
    btree& operator=(const btree &bt);
    // insert new value to binary tree
    void insert(int key);
    // mirror the tree
    void mirror();
    LinkedList* Tree2linkListbyDepth();
    int getTreeDepth();
    // print tree (in order)
    friend std::ostream& operator<<(std::ostream& os, btree& dt);

private:
    node* root;
    bool isMirrored;
    void copyConstructor(node *bt);
    void destroyTree(node * tmp);
    void insert(node* tmp, int key);
    void mirrorInsert(node* tmp, int key);
    void mirror(node * node);
    LinkedList TreeToList(node *tmp, LinkedList *listToReturn, int depth);
    int getTreeDepth(node * tmp);
    friend std::ostream& travel(std::ostream & os, node* root);
};

#endif // _BTREE_H_

btree.cpp

#include"btree.h"
#include"Linkedlist.h"
#include<iostream>
using namespace std;

//constructor
btree::btree()
{
    root = NULL;
    isMirrored = false;
}

//destructor
btree::~btree()
{
    destroyTree(this->root);
}

void btree::destroyTree(node * tmp)
{
    if (tmp == NULL)
        return;
    destroyTree(tmp->left);
    destroyTree(tmp->right);
    delete(tmp);
}

//copy constructor - list to binary tree.
btree::btree(LinkedList &list)
{
    while (list.head!=NULL)
    {
        insert(list.head->data);
        list.head = list.head->next;
    }
}

//copy constructor - inorder.
btree::btree(btree & bt)
{
    if (bt.root == NULL)
        root = NULL;
    else
    copyConstructor(bt.root);
}

void btree::copyConstructor(node *bt)
{
    node* tmp = bt;
    if (!tmp)
        return;
    copyConstructor(tmp->left);
    insert(tmp->key_value);
    copyConstructor(tmp->right);
}

//copying list to binary tree using "=" operator.
btree & btree::operator=(const LinkedList & ls)
{
    Node *tmp = ls.head;
    while (tmp != NULL)
    {
        insert(tmp->data);
        tmp = tmp->next;
    }
    return *this;
}

//copying binary trees using "=" operator
btree & btree::operator=(const btree & bt)
{
    if (this->root == bt.root) //cheking if not itself
        return *this;
    //למחוק את העץ הקיים
    copyConstructor(bt.root);
    return *this;
}

//inserting node to the binary tree
void btree::insert(int key)
{
    node *tmp = root;
    if (root != NULL)
    {
        if (isMirrored)             //checking if the tree has been mirrored
            mirrorInsert(tmp, key);
        else
            insert(tmp, key);
    }
    //if the tree is empty - adding a new node  
    else
    {
        root = new node;
        root->key_value = key;
        root->left = NULL;
        root->right = NULL;
    }
}

//regular insertion - smaller numbers to the left and bigger numbers to the right of the root.
void btree::insert(node* tmp, int key)
{
    if (tmp->key_value >= key)
    {
        if (tmp->left == NULL)
        {
            tmp->left = new node();
            tmp->left->key_value = key;
            tmp->left->left = NULL;
            tmp->left->right = NULL;
            return;
        }
        insert(tmp->left, key);
    }
    else if (tmp->key_value < key)
    {
        if (tmp->right == NULL)
        {
            tmp->right = new node();
            tmp->right->key_value = key;
            tmp->right->left = NULL;
            tmp->right->right = NULL;
            return;
        }
        insert(tmp->right, key);
    }
}

//mirrored insertion - smaller numbers to the right and bigger numbers to the left of the root.
void btree::mirrorInsert(node* tmp, int key)
{
    if (tmp->key_value <= key)
    {
        if (tmp->left == NULL)
        {
            tmp->left = new node();
            tmp->left->key_value = key;
            tmp->left->left = NULL;
            tmp->left->right = NULL;
            return;
        }
        mirrorInsert(tmp->left, key);
    }
    else if (tmp->key_value > key)
    {
        if (tmp->right == NULL)
        {
            tmp->right = new node();
            tmp->right->key_value = key;
            tmp->right->left = NULL;
            tmp->right->right = NULL;
            return;
        }
        mirrorInsert(tmp->right, key);
    }
}

//mirroring the binary tree and keeping track of it.
void btree::mirror()
{
    if (isMirrored)
        isMirrored = false;
    else
        isMirrored = true;
    mirror(root);
}

void btree::mirror(node * node)
{
    if (node == NULL)
        return;
    else
    {
        struct node * tmp;
        mirror(node->left);
        mirror(node->right);

        tmp = node->left;
        node->left = node->right;
        node->right = tmp;
    }
}

//constructing a list of lists, each list contains all the nodes at a specific level(depth).
LinkedList* btree::Tree2linkListbyDepth() 
{
    if (this == NULL)
        return NULL;
    node *tmp = root;
    LinkedList *list;
    int depth = this->getTreeDepth();
    list = new LinkedList[depth];       //list of lists
    
    for (int i = 0; i < depth; i++)
    {
        TreeToList(tmp, &list[i],(depth-i));    //adding to list[i] all the node in (depth-i) level from the binary tree using "TreeToList"
    }
    return list;
}

//returning a list with all the node at a specific level (depth).
LinkedList btree::TreeToList(node *tmp, LinkedList *listToReturn, int depth)
{
    if (tmp == NULL)
        return *listToReturn;
    else if (getTreeDepth(tmp) == depth)
        listToReturn->add(tmp->key_value);
    else
    {
        TreeToList(tmp->left, listToReturn, depth);
        TreeToList(tmp->right, listToReturn, depth);
    }
    return *listToReturn;
}

//returning the binary tree's depth.
int btree::getTreeDepth()
{
    if (this->root == NULL)
        return 0;
    node* tmp = root;
    return getTreeDepth(tmp);
}

int btree::getTreeDepth(node * tmp)
{
    if (tmp == NULL)
        return 0;
    int leftDepth = getTreeDepth(tmp->left);
    int rightDepth = getTreeDepth(tmp->right);
    if (leftDepth > rightDepth)
        return leftDepth+1;
    else
        return rightDepth+1;

}

ostream & travel(ostream &os, node* root)
{
    node* tmp = root;
    if (!root)
        return os;
    travel(os, root->left);
    os << root->key_value << ",";
    travel(os, root->right);
    return os;
}

//printing the binary tree inorder - using recursive function "travel".
ostream & operator<<(ostream & os, btree & dt)
{
    os << "Tree: ";
    travel(os, dt.root);
    os << endl;
    return os;
}

Linkedlist.h

#include <iostream>
#ifndef _LINKEDLIST_H_
#define _LINKEDLIST_H_
class btree;

class Node
{
public:
    Node* next;
    int data;
};
using namespace std;
class LinkedList
{
    friend class btree;
public:
    int length;
    Node* head;

    LinkedList(btree &bt);
    LinkedList(LinkedList &bt);

    LinkedList();
    ~LinkedList();
    
    void add(int data);
    LinkedList & operator=(const LinkedList & bt);
    LinkedList& operator=(const btree &bt);
    friend std::ostream& operator<<(std::ostream& os, LinkedList& l);

private:
    void copyBtToList(struct node *bt);
    LinkedList(const LinkedList &bt);
    void addToTail(int data);
};

#endif // !_LINKEDLIST_H_

Linkedlist.cpp

#include"Linkedlist.h"
#include"btree.h"
#include<iostream>
using namespace std;

LinkedList::LinkedList() {
    length = 0;
    head = NULL;
}
//copy constructors.
LinkedList::LinkedList(LinkedList& other) {
    length = 0;
    if (this->head == other.head)
        return;
    Node* tmp = other.head;
    while (tmp != NULL)
    {
        this->addToTail(tmp->data);
        tmp = tmp->next;
    }
    length = other.length;
}

LinkedList::LinkedList(const LinkedList& other) {
    this->length = other.length;
    if (length == 0)
        return;
    Node* tmp = other.head;
    while (tmp != NULL)
    {
        this->add(tmp->data);
        tmp = tmp->next;
    }
}
//destructor.
LinkedList::~LinkedList() {
    Node* next = head;
    Node* cur = NULL;
    while (next != NULL) {
        cur = next;
        next = next->next;
        delete cur;
    }
}
//copying binary tree to a list.
LinkedList::LinkedList(btree &bt) {
    if (bt.root == NULL)
        this->head = NULL;
    else
        copyBtToList(bt.root);
}

void LinkedList::copyBtToList(node *bt)
{
    node* tmp = bt;
    if (!tmp)
        return;
    
    copyBtToList(tmp->left);
    add(tmp->key_value);
    copyBtToList(tmp->right);

}

//adding node to the head of the list.
void LinkedList::add(int data) {
    Node* node = new Node();
    node->data = data;
    if (head == NULL) { //list is empty
        head = node;
        head->next = NULL;
        length++;
        return;
    }
    node->next = head;
    head = node;
    length++;
}

//adding node to the tail of the list.
void LinkedList::addToTail(int data) {
    Node* node = new Node();
    node->data = data;
    node->next = NULL;
    if (this->length == 0 || head == NULL) { //list is empty
        head = node;
        length++;
        return;
    }

    Node* curr = head;
    while (curr != NULL && curr->next!=NULL)
        curr = curr->next;
    curr->next = node;
    length++;
}

//copying lists using "=" operator.
LinkedList & LinkedList::operator=(const LinkedList & bt)
{
    LinkedList tmp(bt);
    std::swap(tmp.head, this->head);
    return *this;
}

//copying binary tree to list using "=" operator.
LinkedList & LinkedList::operator=(const btree & bt)
{
    LinkedList tmp;
    tmp.copyBtToList(bt.root);
    head = tmp.head;
    return *this;
}

//printing list in the form of "(x1,x2,...,xn)" using "<<" operator.
ostream & operator<<(ostream & os, LinkedList & l)
{
    Node *tmp = l.head;
    os << "List: (";
    while (tmp != NULL)
    {
        os << tmp->data << ",";
        tmp = tmp->next;
    }
    os << ")"<<endl;
    return os;
}

main.cpp

#include"Linkedlist.h"
#include"btree.h"
#include<iostream>
using namespace std;

int main()
{
    btree *tree = new btree();
    tree->insert(10);
    tree->insert(6);
    tree->insert(14);
    tree->insert(5);
    tree->insert(8);
    tree->insert(12);
    tree->insert(16);
    LinkedList* l = tree->Tree2linkListbyDepth();
    int dp = tree->getTreeDepth();
    for (int i = 0; i < dp; i++) {
        cout << l[i];
    }
    cout << *tree;
    tree->mirror();
    cout << *tree;
    btree *tree1 = new btree(l[dp - 1]);
    cout << *tree1;
    btree *tree2 = new btree(*tree1);;
    tree2->insert(100);
    cout << *tree1;
    cout << *tree2;
    LinkedList* l1 = new LinkedList(*tree1);
    LinkedList* l2 = new LinkedList(*l1);
    l2->add(99);
    cout << *l1;
    cout << *l2;
    delete tree;
}

我在 VS 上的输出:

List: (10,)
List: (14,6,)
List: (16,12,8,5,)
Tree: 5,6,8,10,12,14,16,
Tree: 16,14,12,10,8,6,5,
Tree: 5,8,12,16,
Tree: 5,8,12,16,
Tree: 5,8,12,16,100,
List: (16,12,8,5,)
List: (99,16,12,8,5,)

顺便说一句 - 如果您也能检查我的“包含”是否正确完成,我会很高兴,因为我无法轻易弄清楚...
谢谢:)

更新:

我运行你的代码通过AppVerifier。在我尝试 Debug/Release x86/x64 构建的不同变体之前,它最初没有找到任何东西。有一点我让它在 Windows 中崩溃了。然后它停止了崩溃。然后我将所有初始 tree->insert 语句更改为采用 rand() 值而不是固定值,我可以让它在 Windows 中 100% 的时间崩溃。我不确定我是否需要 AppVerifier,但我保留了它。那时我注意到您的 LinkedList 析构函数试图删除 0xcccccccc 处的指针,这是调试版本中未初始化的内存。

底线,这是你的错误:

您的 LinkedList 复制构造函数未将头指针初始化为 NULL

另外,你有两个拷贝构造函数。一个采用非常量引用并且是 public。另一个(行为略有不同)采用 const 引用,但它是私有的。

您只需要一个复制构造函数,它既是 public 又采用 const 引用。

这是解决方法。让这是 public 构造函数:

LinkedList::LinkedList(const LinkedList& other) {
    length = 0;
    head = NULL;  // YOU FORGOT THIS LINE
    Node* tmp = other.head;
    while (tmp != NULL)
    {
        this->addToTail(tmp->data);
        tmp = tmp->next;
    }
    length = other.length;
}

然后删除 LinkedList 复制构造函数的另一个实例。

另一件看起来可疑的事情。您采用链表的 btree 构造函数正在破坏您的列表。 它也忘记在尝试第一次插入之前初始化对象。

btree::btree(LinkedList &list)
{
    while (list.head != NULL)
    {
        insert(list.head->data);
        list.head = list.head->next;
    }
}

这是完全错误的。当您从列表构造 btree 时(通过引用传递),构造函数将修改传入的 LinkedList 实例。当此构造函数 returns 时,list 实例将返回到具有空头指针的调用,但当函数 returns 时返回非零长度成员。并且您的 LinkedList 析构函数将无法递归树来释放内存。所以你有内存泄漏和无效的对象状态。

改为这样做。

btree::btree(const LinkedList &list)
{
    root = NULL;
    isMirrored = false;

    Node* tmp = list.head;
    while (tmp != NULL)
    {
        insert(tmp->data);
        tmp = tmp->next;
    }
}

在构造函数中使用初始化列表也更好:

btree::btree(const LinkedList &list) :
    root(NULL),
    isMirrored(false)
{
    ...
}

不客气:)


旧东西:

您的 cout 语句缺少行尾标记(刷新输出):

而不是这样的语句:

cout << *tree;

这样做:

cout << *tree << endl;

但这不是你的问题。你的程序崩溃了:

[ec2-user@ip-172-31-10-108 stackover]$ g++ main.cpp btree.cpp LinkedList.cpp
[ec2-user@ip-172-31-10-108 stackover]$ ./a.out
List: (10,)
List: (14,6,)
List: (16,12,8,5,)
Tree: 5,6,8,10,12,14,16,
Tree: 16,14,12,10,8,6,5,
Segmentation fault

看起来我们有一个导致崩溃的错误。让我们使用调试构建进行编译并分析:

[ec2-user@ip-172-31-10-108 stackover]$ g++ main.cpp btree.cpp LinkedList.cpp -g
[ec2-user@ip-172-31-10-108 stackover]$ gdb ./a.out
GNU gdb (GDB) Amazon Linux (7.6.1-64.33.amzn1)
...
Reading symbols from /home/ec2-user/stackover/a.out...done.
(gdb) run
Starting program: /home/ec2-user/stackover/./a.out
Missing separate debuginfo for /usr/lib64/libstdc++.so.6
Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/87/91ddd49348603cd50b74652c5b25354d8fd06e.debug
Missing separate debuginfo for /lib64/libgcc_s.so.1
Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/a0/3c9a80e995ed5f43077ab754a258fa0e34c3cd.debug
List: (10,)
List: (14,6,)
List: (16,12,8,5,)
Tree: 5,6,8,10,12,14,16,
Tree: 16,14,12,10,8,6,5,

Program received signal SIGSEGV, Segmentation fault.
0x00000000004011b5 in btree::mirrorInsert (this=0x614ea0, tmp=0x21, key=16) at btree.cpp:133
133         if (tmp->key_value <= key)
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.173.amzn1.x86_64
(gdb)

简短回答:看起来您需要围绕 btree.cpp 的第 133 行进行一些额外的调试。 tmp 的值为 0x21 - 这可能不是合法的指针值。