【问题标题】:What is wrong with this C++ code? It crashes on run这段 C++ 代码有什么问题?它在运行时崩溃
【发布时间】:2012-10-23 05:13:58
【问题描述】:

我想知道以下 C++ 代码有什么问题。它在运行时崩溃。

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

class node
{
    public:
        int info;
        node *addr;

        node(){
            info = 0;
            addr = NULL;          
        }

        ~node(){}
};

void func(node *);


int main(void){   
    node *head;
    node b;

    b.info = 10;

    *head = b;

    func(head); 
    getch();
}

void func(node *obj){
    cout<<"i: "<<(*obj).info;
}

【问题讨论】:

  • 即使在func(node *) 函数中将cout&lt;&lt;"i: "&lt;&lt;(*obj).info; 替换为cout&lt;&lt;"i: "&lt;&lt;(obj-&gt;info);,问题仍然存在
  • 你必须分配你的类,即b = new node(),然后访问元素如b->info = 10
  • *head = b; 应该是head = &amp;b;
  • 当程序为您崩溃时,您的第一反应应该是在调试器中运行该程序。它将帮助您定位崩溃的位置,还可以让您检查变量以帮助您了解崩溃的原因
  • b = new node() 不等于 node b; 吗??

标签: c++ pointers nodes


【解决方案1】:
*head = b;

不正确,因为 head 没有指向任何东西

head = &b ;

应该解决问题

【讨论】:

  • 请注意b 是一个堆栈对象,所以head 在函数完成后无效。当然head也仅限于main(),但是边学边做也不是很安全。
【解决方案2】:

看来问题出在

*head = b;

替换为

head = &b ;

【讨论】:

    【解决方案3】:

    有一个问题是你在这里声明了一个指针:

    node *head;
    

    然后在这里使用它:

     *head = b;
    

    没有为head分配内存。

    【讨论】:

      【解决方案4】:

      假设您要将b 的地址分配给指针head,则*head = b; 行应该改为head = &amp;b;

      错误的版本可以编译,但它会将对象b 的副本分配给未初始化指针中包含的地址。

      【讨论】:

        【解决方案5】:

        其他人已经回答了您写入任意内存的问题,但我想专注于其他一些事情,例如:

        #include <iostream.h>
        #include <conio.h>
        

        问题在于您使用的编译器严重 过时了。 C++ 头文件不再有.hconio.h 严重不标准且老化。

        我建议您首先更新到更新的环境。

        此外,OO 的基石之一是对象对自己的行为负责。 从不让代码直接访问对象内部以直接访问成员是一个好主意。

        您应该提供适当的 getter 和 setter,并通常确保您的类中唯一的 public 东西是函数而不是数据。

        换句话说,类似于:

        class node {
            public:
                node () {
                    info = 0;
                    addr = NULL;          
                }
        
                ~node() {
                }
        
                int getInfo() {
                    return info;
                }
                void setInfo (int newInfo) {
                    // Check newInfo for validity first.
                    info = newInfo;
                }
        
                node *getAddr() {
                    return addr;
                }
                void setAddr (node *newAddr) {
                    // Check newAddr for validity first.
                    addr = newAddr;
                }
        
            private:
                int info;
                node *addr;
        
        };
        

        【讨论】:

        • 我在这两点上都同意你的观点,但我发现自己越来越多地在简单的情况下使用 POD 风格的结构。如果您正在创建一个供全球数千名程序员使用的库,这是一回事,但如果您正在编写一些简单的日志工具,供您和 3 或 10 个人在一家较小的软件商店使用,它实际上节省了时间和精力具有“mOutputFile”句柄,而不是“GetOutputFile()”函数。经过一段时间的专业工作后,这只是我的个人意见。
        • @Rollie,如果一切都是公开的,你也可以使用 struct 并保存一行代码:-)
        • @paxdiablo: 非常感谢您提供这些宝贵的信息.. 显然我还没有学习最新的编程标准... 从高中开始我就被教导使用 conio.h.. 和我无法摆脱它。请您向我指出您认为我应该采用的有关编程风格的资源吗?
        • @paxdiablo 我同意,并且这样做:P 对我来说,他们在 C++ 中打扰“类”和“结构”似乎有点愚蠢,并且有一个模板参数类型“类”,它对初学者来说有点混乱,而 'typename' 更明确一些。
        • @Jugesh,与其说是编程风格,不如说是尽可能地遵循标准(假设你对代码的可移植性感兴趣——如果你要做的只是微软的东西,那么便携性可能是次要问题)。 comio 让人想起 Borland/Inprise/Encilada 的鼎盛时期(或者他们现在自称的任何东西),大多数人只是将它用于 getch(当标准中有一个非常好的 getchar 时)。
        【解决方案6】:

        我看到两个问题:

        1. 你引用了一个未初始化的指针*head

        2. 您将堆栈变量存储在指针中。

        我(和其他人一样)认为,当您说 *head = b 时,您的真正意思是 head = &amp;b。在第一种情况下,您引用一个节点指针并在其上分配一个节点值。这是一个错误,因为 head 变量尚未初始化,因此您在无效的内存地址之上复制了一个完整的节点值。

        如果换成head = &amp;b会好一点,因为现在你把head指针设置为b的地址。但是现在您遇到了另一个错误,因为b 是一个堆栈变量,因此那里的指针仅在函数的生命周期内有效。一旦函数完成,堆栈空间将被重用,head 指针会破坏那里的任何东西。

        典型的解决方案是将head 保留为指向节点的指针,但也将b 更改为指向节点的指针,并使用堆内存分配对其进行初始化,例如b = (node *)malloc(sizeof(node);b = new node;。然后你可以在*b中存储任何东西,最后,将指针存储到一个寿命更长的变量,比如heap=b;

        【讨论】:

          猜你喜欢
          • 2018-01-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-21
          • 2018-10-28
          • 1970-01-01
          • 2019-10-27
          相关资源
          最近更新 更多