【问题标题】:Program received signal SIGSEGV, Segmentation fault. C++ LIST程序收到信号 SIGSEGV,分段错误。 C++ 列表
【发布时间】:2018-01-31 14:12:55
【问题描述】:
如果我在 L.deleteElement() 之后调用

L.insert(),则会出现分段错误。 这是错误信息:

196     nPtr = (nodePtr)malloc(sizeof(node));
(gdb) print(c)
$7 = 2
(gdb) next
197     if(nPtr!=NULL){
(gdb) print(nPtr)
$8 = (nodePtr) 0x615c70
(gdb) next
198         nPtr->data = element;
(gdb) print(element)
$9 = "("
(gdb) next

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b74413 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_assign(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6

我创建了一个新节点并且没有取消引用任何未初始化的指针!谁能解释我为什么会收到此错误?它按预期工作,直到我在 L.deleteEle() 之后调用它。

这是我的完整程序:

#include<iostream>
#include<stdlib.h>
#include<string>
using namespace std;
struct node
{
    string data;
    struct node *next;
};
typedef struct node node;
typedef node* nodePtr;
class List
{
    nodePtr head;
    int count;
    nodePtr tail;
public:
    List(nodePtr h=NULL,int c=0,nodePtr t=NULL){ // constructor
        head=h;
        count=c;
        tail=t;
    } 
    bool insert(string element, int position=1); // if position is invalid, returns false ; takes default position as START (1)
    bool deleteEle(int position); // deletes the node at specified position, else returns false.
};

bool List::deleteEle(int position)
{
    if(position>count){
        return false;
    }
    nodePtr pPtr;
    nodePtr cPtr;
    nodePtr tPtr;
    int p=position;
    if(position==1){
        cPtr=head;
        tPtr=cPtr->next;
        head=tPtr;
        free(cPtr);
        count-=1;
        return true;
    }
    cPtr=head;
    pPtr=NULL;
    while(p>1){
        pPtr=cPtr;
        cPtr=cPtr->next;
        p--;
    }
    if(position==count){
        tail=pPtr;
        tail->next=NULL;
        free(cPtr);
        count-=1;
        return true;
    }
    tPtr=cPtr->next;
    pPtr->next=tPtr;
    free(cPtr);
    count-=1;
    return true;
}
bool List::insert(string element, int position)
{
    if (position>count+1){
        return false;
    }
    int c = position;
    nodePtr nPtr;
    nodePtr tPtr;
    nodePtr cPtr;
    nPtr = (nodePtr)malloc(sizeof(node));
    if(nPtr!=NULL){
        nPtr->data = element;
        nPtr->next = NULL;

        tPtr = NULL;
        cPtr = head;
        if(cPtr==NULL){
            head=nPtr;
            tail=nPtr;
            count+=1;
            return true;
        }
        else if(position==count+1){
            cout<<"ikkade !!!";
            tail->next=nPtr;
            tail=nPtr;
            count+=1;
            return true;
        }
        else if(position==1){
            head=nPtr;
            nPtr->next=cPtr;
            count+=1;
            return true;
        }
        else{
            while(cPtr!=NULL && c>2){
                cPtr = cPtr->next;
                c--; 
            }
            tPtr=cPtr->next;
            cPtr->next=nPtr;
            nPtr->next=tPtr;
            count+=1;
            return true;
        }
    }
    else{
        cout<<element<<" not inserted! No memory available.";
        return false;
    }
}
int main(void)
{
    List L;
    L.insert("(",L.size()+1);
    L.insert("+",L.size()+1);
    L.deleteEle(L.size());
    L.insert("(",L.size()+1); //fails here
return 0;       
}

调用 deleteEle 后插入失败!

【问题讨论】:

  • 您在声称是 C++ 程序的情况下使用 C 风格的 malloc/free 内存分配是什么?
  • 又一位 C++ 学生献祭给链表之神。
  • 如果插入和类定义不显示代码,我们应该如何帮助您?您的调试器跟踪甚至看起来不像是通过您发布的函数运行。
  • 不要使用mallocfree。如果 nodePtr 指向与 C 布局不兼容的东西(POD 类型),则对 malloc 的调用会调用未定义的行为。
  • 啊哈,就像我说的,使用malloc 是行不通的。您的 node 类包含 std::string。您从哪里得到使用malloc 的想法?即使是非常糟糕的 C++ 书籍也不会让学生使用malloc。这是你的主意吗?

标签: c++ linked-list segmentation-fault


【解决方案1】:

可能导致分段错误的一个问题是在 C++ 程序中(错误)使用 mallocfree 来动态创建对象。

这个结构:

struct node
{
    string data;
    struct node *next;
};

然后是执行此操作的代码:

nPtr = (nodePtr)malloc(sizeof(node));

不创建node 对象,因为node 的构造函数没有被调用,因此std::string 的默认构造函数没有被调用。

所有malloc 所做的只是分配sizeof(node) 字节——实际上没有创建node 对象。您现在只剩下一堆分配的字节,它们不会形成任何类型的node 对象。任何将nPtr 当作有效对象的使用都会调用未定义的行为。

不要使用mallocfree,而是使用newdelete,因为new 调用对象的构造函数,而malloc 不调用,此外,delete 调用free 没有析构函数。

因此,将您现在正在进行的 mallocfree 调用替换为以下内容(当然,在必要时更改变量的名称):

nPtr = new node;

然后当完成时:

delete nPtr;


现在malloc 在创建对象时有其用途——它可以用于诸如placement-new 之类的事情,您可以在其中发出对malloc 的调用,然后使用它来创建对象。但显然你的代码没有使用placement-new

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    相关资源
    最近更新 更多