C++ 错误C6011:取消引用空指针';名称';。C++;

C++ 错误C6011:取消引用空指针';名称';。C++;,c++,inner-classes,null-pointer,C++,Inner Classes,Null Pointer,正如在标题中,我的代码给出了上述警告,并将内存引用混搭在一起。 我被设计使用C++中的嵌套类。此代码主要是我以前C应用程序中链表的代码,但为C++重新编写。 我在互联网上搜索过这个空异常,但我想不出来。 我会发布代码,希望有人能给我一些提示。 在互联网上的各种链接和提示中,它说我指向的指针引用了一个空ptr,它不能访问空地址。 试图以各种形式对其进行审查,但不起作用 标题 #ifndef LIST_H #define LIST_H #include <iostream> #incl

正如在标题中,我的代码给出了上述警告,并将内存引用混搭在一起。 我被设计使用C++中的嵌套类。此代码主要是我以前C应用程序中链表的代码,但为C++重新编写。 我在互联网上搜索过这个空异常,但我想不出来。 我会发布代码,希望有人能给我一些提示。 在互联网上的各种链接和提示中,它说我指向的指针引用了一个空ptr,它不能访问空地址。 试图以各种形式对其进行审查,但不起作用

标题

#ifndef LIST_H
#define LIST_H

#include <iostream>
#include <math.h>
using namespace std;

class List
{
private:
    class Node {
    public:
        int data;
        Node* next;
        Node() {
            this->data = NULL;
            this->next = NULL;
        }
    };
    Node* head;
public:
    List();
    void insertList(int data);
    void deleteFromList(int data);
    void deleteLowerThan(int lower);
    void calculateArithmetic();
    void showList();
};

#endif


问题出在
deleteFromList
函数中,代码如下:

while(临时->数据!=n&&temp!=NULL){
//...
在这里,您试图在验证
temp
是否为
NULL
之前检查
temp->data的值。因此,您将在某个点(当您在列表末尾时,
temp
NULL
取消引用空指针,这不好

相反,只需颠倒比较顺序:

while(temp!=NULL&&temp->data!=n){
//...

这样,只要
temp
NULL
,比较结果将被完全知道(请参阅),
temp->data
不进行计算,循环将停止运行。

问题在于
deleteFromList
函数,使用此代码:

while(临时->数据!=n&&temp!=NULL){
//...
在这里,您试图在验证
temp
是否为
NULL
之前检查
temp->data的值。因此,您将在某个点(当您在列表末尾时,
temp
NULL
取消引用空指针,这不好

相反,只需颠倒比较顺序:

while(temp!=NULL&&temp->data!=n){
//...

通过这种方式,只要
temp
NULL
,比较结果就会被完全知道(请参阅),
temp->data
不进行计算,循环将停止运行。

正如Adrian和Andy指出的,这一行导致
temp
在检查
NULL
之前取消引用

while (temp->data != n && temp != NULL)
因此,只需先检查它不是
NULL
,然后取消引用它

其他值得一提的问题是内存泄漏。对于每个
新的
,您应该只有一个
delete
(除非您将指针交给一个智能指针,该指针将为您执行
delete

您还需要在
列表
中实现析构函数,以便在销毁
列表
时删除该列表中的所有节点

deleteLowerThan()
函数中存在一个更棘手的错误。您迭代列表中的节点并调用
deleteFromList()
,这将删除当前所在的节点。在下一次迭代中,您在
if(temp->data
导致未定义的行为。在我的例子中,程序似乎永远挂起

一个可能的解决方案:

void List::deleteLowerThan(int n) {
    Node* temp = head;
    int tmpdata;

    while(temp != nullptr) {
        tmpdata = temp->data; // save the nodes data
        temp = temp->next;    // step before you delete
        if(tmpdata < n) {
            deleteFromList(tmpdata);
        }
    }
}
void List::deleteLowerThan(int n){
节点*温度=头部;
int-tmpdata;
while(temp!=nullptr){
tmpdata=temp->data;//保存节点数据
temp=temp->next;//删除前的步骤
如果(tmpdata
正如Adrian和Andy所指出的,在检查
是否为空之前,这一行会导致
temp
被取消引用

while (temp->data != n && temp != NULL)
因此,只需先检查它不是
NULL
,然后取消引用它

其他值得一提的问题是内存泄漏。对于每个
新的
,您应该只有一个
delete
(除非您将指针交给一个智能指针,该指针将为您执行
delete

您还需要在
列表
中实现析构函数,以便在销毁
列表
时删除该列表中的所有节点

deleteLowerThan()
函数中存在一个更棘手的错误。您迭代列表中的节点并调用
deleteFromList()
,这将删除当前所在的节点。在下一次迭代中,您在
if(temp->data
导致未定义的行为。在我的例子中,程序似乎永远挂起

一个可能的解决方案:

void List::deleteLowerThan(int n) {
    Node* temp = head;
    int tmpdata;

    while(temp != nullptr) {
        tmpdata = temp->data; // save the nodes data
        temp = temp->next;    // step before you delete
        if(tmpdata < n) {
            deleteFromList(tmpdata);
        }
    }
}
void List::deleteLowerThan(int n){
节点*温度=头部;
int-tmpdata;
while(temp!=nullptr){
tmpdata=temp->data;//保存节点数据
temp=temp->next;//删除前的步骤
如果(tmpdata
您可能希望在此处切换顺序:
while(temp->data!=n&&temp!=NULL)
您可能希望在此处切换顺序:
while(temp->data!=n&&temp!=NULL)
@Vlad您使用的是哪种编译器?如果您使用的是
g++
,您可以添加
-fsanize=undefined-fsanize=address-g3
,以获得它发生的确切函数和行号,并且它确实发生在Adrian指出的行中。更改此选项可以避免崩溃,但会使程序进入一个永久循环。@tedlynmo你能解释一下永恒循环发生在哪里吗?(我不是说它不发生,只是看不到发生在哪里。)我也不能…现在。我运行它时只是一个观察:-)这个程序充满了内存泄漏,因此它可能与.UB有关。@Vlad您使用的是哪种编译器?如果您使用的是
g++
,您可以添加
-fsanize=undefined-fsanize=address-g3
,以获得它发生的确切函数和行号,这确实发生在Adrian指出的行中
void List::deleteLowerThan(int n) {
    Node* temp = head;
    int tmpdata;

    while(temp != nullptr) {
        tmpdata = temp->data; // save the nodes data
        temp = temp->next;    // step before you delete
        if(tmpdata < n) {
            deleteFromList(tmpdata);
        }
    }
}