C++14 代码应该导致分段错误,因为列表1头部的浅拷贝节点被删除,但列表2头部仍然指向那个里

C++14 代码应该导致分段错误,因为列表1头部的浅拷贝节点被删除,但列表2头部仍然指向那个里,c++14,copy-constructor,shallow-copy,C++14,Copy Constructor,Shallow Copy,由于浅拷贝,该代码应该会导致分段错误,但相反,当main()中的list2调用printAll()时,它允许打印list2的头节点的地址。应该怎么做才能获得预期的行为?还请解释为什么会发生这种情况?我是初学者,先谢谢你 >>>> when tried with #pragma pack(1) it resuted in the first output >>>> Without #pragma pack(1) it resulted in the

由于浅拷贝,该代码应该会导致分段错误,但相反,当main()中的list2调用printAll()时,它允许打印list2的头节点的地址。应该怎么做才能获得预期的行为?还请解释为什么会发生这种情况?我是初学者,先谢谢你

>>>> when tried with #pragma pack(1) it resuted in the first output

>>>> Without #pragma pack(1) it resulted in the second output



Here is the code i wrote.
The code is for creating an object (list1) of SLL class(singly linked list) and copying it to another object(list2) of SLL class.
#include <iostream>
using namespace std;

//#pragma pack(1)
class Node{
        public:
                char letter;
                Node *next;
};
class SLL{
        private:
                Node *head, *tail;
        public:
                SLL(){
                        head = NULL;
                        tail = NULL;
        }
        void printAll();// for printing the list
        void insertNewNode(char item);// for insertion at head                                
        //function for deletion at head
        void deleteAtHead(){ 
                   Node *tmp;
                   tmp = this->head;
                   this->head = this->head->next;
                   free(tmp);
        }
};
//it is for printing a singly linked list
void SLL::printAll(){

        Node *p;
        p = head;
        cout<<"VALUE  "<<"           "<<"  ADDRESS"<<endl;
        while(p!=NULL){
                cout <<p->letter << "--------------- "<<p<<endl;
                p = p->next;
        }
}
void SLL::insertNewNode(char item){
        Node* temp;
        temp = (Node *)malloc(sizeof(Node));
        temp->letter = item;
        temp->next = head;
        head = temp;
}
int main(){
        SLL list1;
        list1.insertNewNode('D');
        list1.insertNewNode('C');
        list1.insertNewNode('B');
        list1.insertNewNode('A');

        cout<<"PRINTING LIST1"<<endl;
        list1.printAll();
        cout<<""<<endl;

        cout<<"SHALLOW COPY INVOKED"<<endl;
        SLL list2 = list1;
        cout<<""<<endl;

        cout<<"PRINTING LIST2"<<endl;
        list2.printAll();

        list1.deleteAtHead();
        cout<<""<<endl;

        cout<<" LIST1 AFTER ITS HEAD DELETION"<<endl;
        list1.printAll();
        cout<<""<<endl;

        cout<<" LIST2"<<endl;
        list2.printAll();       // as soon as this is executed it should result in runtime error
        return 0;
}


>>>>>>> Output1:
PRINTING LIST1
VALUE               ADDRESS
 A ------------- 0x5578d6f872e0
 B ------------- 0x5578d6f872c0
 C ------------- 0x5578d6f872a0
 D ------------- 0x5578d6f87280

SHALLOW COPY INVOKED

PRINTING LIST2
VALUE               ADDRESS
 A ------------- 0x5578d6f872e0
 B ------------- 0x5578d6f872c0
 C ------------- 0x5578d6f872a0
 D ------------- 0x5578d6f87280

 LIST1 AFTER ITS HEAD DELETION
VALUE               ADDRESS 
 B  ------------- 0x5578d6f872c0
 C  ------------- 0x5578d6f872a0
 D  ------------- 0x5578d6f87280

 LIST2
VALUE               ADDRESS
  --------------- 0x5578d6f872e0

>>>>>> Output2:

PRINTING LIST1
VALUE               ADDRESS
 A ------------- 0x55baac1032e0
 B ------------- 0x55baac1032c0
 C ------------- 0x55baac1032a0
 D ------------- 0x55baac103280

SHALLOW COPY INVOKED

PRINTING LIST2
VALUE               ADDRESS
 A  ------------- 0x55baac1032e0
 B  ------------- 0x55baac1032c0
 C  ------------- 0x55baac1032a0
 D  ------------- 0x55baac103280

 LIST1 AFTER ITS HEAD DELETION
VALUE               ADDRESS
 B  ------------- 0x55baac1032c0
 C  ------------- 0x55baac1032a0
 D  ------------- 0x55baac103280

 LIST2
VALUE               ADDRESS
--------------- 0x55baac1032e0
B--------------- 0x55baac1032c0
C--------------- 0x55baac1032a0
D--------------- 0x55baac103280
>当使用#pragma pack(1)进行尝试时,它会在第一次输出中恢复
>>>>如果没有#pragma pack(1),则会产生第二个输出
这是我写的代码。
代码用于创建SLL类(单链表)的对象(list1)并将其复制到SLL类的另一个对象(list2)。
#包括
使用名称空间std;
//#布拉格语包(1)
类节点{
公众:
字符字母;
节点*下一步;
};
类SLL{
私人:
节点*头,*尾;
公众:
SLL(){
head=NULL;
tail=NULL;
}
void printAll();//用于打印列表
void insertNewNode(char项);//用于在头部插入
//用于在头部删除的功能
void deleteAthad(){
节点*tmp;
tmp=此->头部;
本->头=本->头->下一步;
免费(tmp);
}
};
//它用于打印单链表
void SLL::printAll(){
节点*p;
p=水头;

指针指向内存的某个区域。任何内存区域。 程序从操作系统获取内存,操作系统通常将内存分成大块(“页面”),然后程序运行时将其细分。malloc调用的例程new和free、delete都会这样做,但调用和返回子程序的机制也会这样做

试图使用内存中未分配给程序的位置会导致分段错误。但使用分配给程序的内存不会导致错误

程序通常不会返回分配给它们的页面。相反,内存只是重复使用,例如存储不同的变量。这是一种优化,因为操作系统分配内存需要花费大量精力。它还减少了程序使用的缓存量


这就是所谓的“悬空指针”如此危险的原因。当你使用它时,它会返回数据。只有仔细检查才会发现数据毫无意义。它甚至可能在很长一段时间内返回正确的数据,直到内存区域被回收并被其他内容覆盖。然后你的程序突然显示“未定义的行为”…

C++14 h作为智能指针。使用它们。它还有内置的列表。也可以使用它们。@EvertW作为学习过程的一部分,我正在尽可能多地探索,因此我尝试了它。你正在教自己重新发明轮子。你应该尽可能好地使用语言,制作一个对你有用/有趣的程序。智能指针和列表,在标准模板库中发现的哈希映射等使低级内存管理过时。在现代C++中,你几乎不应该直接使用新的、删除和指针算法。@ C++中的EvertW总是面临低层次的实现细节。(到写一个正确的链表所需的程度),你将无法得到任何地方。请不要劝阻人们学习那些肮脏的基础。换句话说,不要在C++中使用<代码> MalcC 和<代码>免费< /代码>(警告适用)。,它们不会调用正确的构造函数和析构函数。在学习时使用
new
delete
,在编写“真实世界的代码”时使用智能指针。更清楚的是,它从一开始就是未定义的行为。它可能不会在任何可观察的事物中表现出来(即,它可能会继续做“正确的事情”)直到后来,但它仍然是未定义的行为。但它也可能在你“达到”代码之前就显现出来:@MaxLanghof:yes,这种特殊类型的错误的痛苦是多方面的,痛苦的。只是比种族条件稍微好一点。。。