c ++删除指针问题,仍然可以访问数据[关闭]

Posted

技术标签:

【中文标题】c ++删除指针问题,仍然可以访问数据[关闭]【英文标题】:c++ delete pointer issue, can still access data [closed] 【发布时间】:2011-12-11 06:24:38 【问题描述】:

我真的不明白为什么这些指针可以访问......任何帮助表示赞赏

#include <iostream>

class Wicked
public:
    Wicked() ;
    virtual ~Wicked() ;

    int a;
    int b;
;


class Test

public:
    Test() ;
    virtual ~Test() ;

    int c;

    Wicked * TestFunc()
    
        Wicked * z;
        c = 9;
        z = new Wicked;
        z->a = 1;
        z->b = 5;
        return z;
    ;
;

int main()

    Wicked *z;

    Test *t = new Test();
    z = t->TestFunc();

    delete z;
    delete t;

    // why can I set 'z' when pointer is already destroyed?
    z->a = 10;

    // why does z->a print 10?
    std::cout << z->a << std::endl;

    // why does t->c exist and print correct value?
    std::cout << t->c << std::endl;

    //------------------------------------------------------

    int * p = new int;
    *p = 4;

    // this prints '4' as expected
    std::cout << *p << std::endl;

    delete p;

    // this prints memory address as expected
    std::cout << *p << std::endl;

    return 0;

【问题讨论】:

我不太明白这是什么问题。 除非你改写你的问题,否则我猜它很快就会关闭。 删除'z'和't'指针后,它们仍然打印值 OP 询问如何在删除指针后获得旧值,即内存是可访问的。我认为这个问题没有问题 C++ delete - It deletes my objects but I can still access the data? 的可能重复项 【参考方案1】:

删除指针不会将任何内存清零,因为这样做会占用 CPU 周期,而这不是 C++ 的意义所在。你所拥有的是一个悬空指针,并且可能是一个微妙的错误。像这样的代码有时可以工作多年,但在将来某个时间点在程序的其他地方进行一些小的更改时崩溃。

这是一个很好的理由,当你删除指针指向的内存时,你应该将指针清空,这样如果你试图取消引用指针,你会立即得到一个错误。有时,使用 memset() 之类的函数清除指向的内存也是一个好主意。如果内存指向的内存包含您不希望程序的其他部分(可能是面向用户的部分)访问的机密信息(例如明文密码),则尤其如此。

【讨论】:

NULL'ing 指针可能会导致其他类型的错误被隐藏(可能很长一段时间)。最好只使用智能指针,甚至不要陷入这种情况。此外,也不能保证取消引用 NULL 指针会产生错误(比其他位置更多)最好不要依赖它来检测错误。 取消引用 NULL 指针是未定义的行为,所以是的,我想它可以做任何事情,但是您是否知道不会立即执行分段错误的实现?我想我从来没有见过这个。尽管我很喜欢智能指针,但其中一些也可能存在缺陷。例如 smart_ptr 的循环引用问题可能是调试的噩梦。虽然我同意你,但如果它适合你的使用,uniq_ptr 是合理的故障安全。 有几个。实际上有几个关于 SO 的问题是问“为什么当我取消引用 NULL 时它没有崩溃”。 how-can-dereferencing-a-null-pointer-in-c-not-crash-a-program 我猜你实际上并没有阅读你链接到的那个问题,OP 在他的“解决方案”部分中说“有问题的指针不是 NULL”,结果他期待将指针删除为 NULL。 奥普斯。你是写我没有读它我只是假设人们足够聪明来写一个好的标题。我想人们比我想相信的还要愚蠢(包括我自己)。【参考方案2】:

那是undefined behaviour。任何事情都有可能发生。这次你很幸运。或者可能是不幸的,因为最好得到一个运行时错误!下一次也许你会得到一个运行时错误。

推理为什么您会看到未定义行为的特定表现并不是很有用。最好坚持您可以推理的明确定义的行为。

【讨论】:

“未定义的行为”需要引用 @Talespin_Kit 你认为它是实现定义而不是未定义? 我正在寻找来自 c++ 标准的引用。我找不到任何权威来源。 @Talespin_Kit 哪个版本的标准?这个问题已经超过 8 年了。【参考方案3】:

C++ 不会阻止您写入内存中的任意位置。当您使用newmalloc 分配内存时,C++ 会在内存中找到一些未使用的空间,将其标记为已分配(这样它就不会意外地再次被分配),并为您提供它的地址。

然而,一旦您delete 该内存,C++ 会将其标记为免费,并可能将其分发给任何需要它的人。您仍然可以对其进行写入和读取,但此时,其他人可能正在使用它。当您写入内存中的那个位置时,您可能会覆盖您在其他地方分配的某些值。

【讨论】:

【参考方案4】:

这里

// why can I set 'z' when pointer is already destroyed?
z->a = 10;

z 仍然指向一个内存位置。 但它不再适合你。您已将其传递给 delete 并说要注意这个指针。它的作用不再是您关心的问题。就像你卖车一样;它仍然存在,但它不是你的,所以打开门并查看可能是可能的,但它可能会导致警察逮捕你。

与删除的指针相同,内存存在但不属于您。 如果您查看内部,它可能会起作用,但它也可能导致分段错误,因为库已刷新页面(您永远不知道)。

【讨论】:

【参考方案5】:

delete z; 只是释放z 指向的内存,它不会破坏指针本身。

所以z 变成了wild pointer。

【讨论】:

【参考方案6】:

因为删除一块内存不会使指向它的所有指针的值归零。删除内存只是说明内存可用于分配其他用途。在此之前,内存可能看起来是完整的——但你不能指望它,并且在某些编译器/运行时/架构组合上,你的程序会表现不同——它甚至可能崩溃。

【讨论】:

以上是关于c ++删除指针问题,仍然可以访问数据[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

数据访问:Django 表单与 request.POST 方法 [关闭]

我在删除指针时遇到读取访问冲突[关闭]

不用密码访问数据库? [关闭]

C如何检查内存地址是不是仍在范围内[关闭]

C ++ - 保存和删除[关闭]

我可以删除指针但保留变量吗[关闭]