【问题标题】:Why isn't this program crashing? (shallow copy)为什么这个程序没有崩溃? (浅拷贝)
【发布时间】:2020-12-05 00:34:30
【问题描述】:

我正在学习拷贝构造函数和浅拷贝和深拷贝。我在关注这个视频:Copying and Copy Constructors in C++

以下代码是直接从视频中复制过来的,演示了浅拷贝……(视频中9点30分)

这段代码应该在运行后崩溃,因为解构器会尝试两次释放相同的内存(第一次是string,后来是string2)。第一次删除应该可以正常工作,但第二次删除应该会导致程序崩溃,因为我们正在尝试删除未分配的内存。

令人惊讶的是,我的情况并没有发生这种情况。我在命令提示符下使用g++ copying_and_copy_constructor.cpp 编译了代码,它编译良好并使用a.exe 运行它。没有错误。

#include<iostream>
#include<cstring>
#include<string>

using std::endl;
using std::cout;


class String
{
private:
    char* m_Buffer;
    unsigned int m_size;
public:
    String(const char* string)
    {
        m_size = strlen(string);
        m_Buffer = new char[m_size+1];
        memcpy(m_Buffer,string,m_size);
        m_Buffer[m_size] = 0;
    }

    ~String()
    {
        delete [] m_Buffer;
    }


    friend std::ostream& operator << (std::ostream& stream, const String& string);
};


std::ostream& operator<<(std::ostream& stream, const String& string)
{
    stream<< string.m_Buffer;
    return stream;
}


int main()
{
    String string = "My string";
    String string2 = string;

    cout<<string2<<endl;
    cout<<string;
    return 0;
}

我什至尝试检查调试器。我使用g++ -g copying_and_copy_constructor.cpp 编译代码,然后使用gdb a.exe。这是它的输出:

GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\a.exe...done.
(gdb) start
Temporary breakpoint 1 at 0x401446: file copying_and_copy_constructor.cpp, line 43.
Starting program: D:\a.exe
[New Thread 44892.0x8258]
[New Thread 44892.0x6df8]
[New Thread 44892.0xadd8]
[New Thread 44892.0x9658]

Temporary breakpoint 1, main () at copying_and_copy_constructor.cpp:43
43              String string = "My string";
(gdb) c
Continuing.
My string
My string[Inferior 1 (process 44892) exited normally]
(gdb)
The program is not being run.
(gdb) q

这条线让我很困惑My string[Inferior 1 (process 44892) exited normally]。这段代码如何正常退出?

视频中的人正在使用 VS-Code...我如何在命令提示符下得到同样的错误?

如视频所示崩溃:

(我现在没有vs代码(以后可能会安装))

【问题讨论】:

  • 未定义的行为可能导致任何事情,包括明显的良好功能。不保证崩溃。
  • 哦...我以为我使用 gdb 错误或类似的东西。那么调试这些错误一定是一场噩梦:(
  • @Yatin 这就是为什么你需要一个好的调试器。更好的调试器比更好的编译器更好。

标签: c++ debugging visual-studio-code gdb shallow-copy


【解决方案1】:

对我来说(Fedora 32 x86_64)确实会崩溃:

$ g++ -o q q.C -Wall -g;./q
My string
free(): double free detected in tcache 2
Aborted

但我绝对同意这样的代码看起来运行良好。这就是为什么会有ASAN

$ g++ -o q q.C -Wall -g -fsanitize=address;./q
My string
=================================================================
==3388436==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0:
    #0 0x7fb76f262cd7 in operator delete[](void*) (/lib64/libasan.so.6+0xb2cd7)
    #1 0x4016e9 in String::~String() /home/jkratoch/t/q.C:25
    #2 0x40144b in main /home/jkratoch/t/q.C:42
    #3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308
    #4 0x40120d in _start (/quad/home/jkratoch/t/q+0x40120d)

0x602000000010 is located 0 bytes inside of 10-byte region [0x602000000010,0x60200000001a)
freed by thread T0 here:
    #0 0x7fb76f262cd7 in operator delete[](void*) (/lib64/libasan.so.6+0xb2cd7)
    #1 0x4016e9 in String::~String() /home/jkratoch/t/q.C:25
    #2 0x40143e in main /home/jkratoch/t/q.C:43
    #3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308

previously allocated by thread T0 here:
    #0 0x7fb76f2621d7 in operator new[](unsigned long) (/lib64/libasan.so.6+0xb21d7)
    #1 0x4015d6 in String::String(char const*) /home/jkratoch/t/q.C:18
    #2 0x4013a0 in main /home/jkratoch/t/q.C:42
    #3 0x7fb76ecbc041 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: double-free (/lib64/libasan.so.6+0xb2cd7) in operator delete[](void*)
==3388436==ABORTING

如果您不想甚至无法使用-fsanitize=address 重新编译程序,您可以使用Valgrind(但速度较慢且无法检测到所有内容):

$ g++ -o q q.C -Wall -g;valgrind ./q
==3388447== Memcheck, a memory error detector
==3388447== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3388447== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info
==3388447== Command: ./q
==3388447== 
My string
==3388447== Invalid free() / delete / delete[] / realloc()
==3388447==    at 0x483C59C: operator delete[](void*) (vg_replace_malloc.c:649)
==3388447==    by 0x40139E: String::~String() (q.C:25)
==3388447==    by 0x401277: main (q.C:42)
==3388447==  Address 0x4db5c80 is 0 bytes inside a block of size 10 free'd
==3388447==    at 0x483C59C: operator delete[](void*) (vg_replace_malloc.c:649)
==3388447==    by 0x40139E: String::~String() (q.C:25)
==3388447==    by 0x40126B: main (q.C:43)
==3388447==  Block was alloc'd at
==3388447==    at 0x483B582: operator new[](unsigned long) (vg_replace_malloc.c:431)
==3388447==    by 0x401334: String::String(char const*) (q.C:18)
==3388447==    by 0x40121B: main (q.C:42)
==3388447== 
My string==3388447== 
==3388447== HEAP SUMMARY:
==3388447==     in use at exit: 0 bytes in 0 blocks
==3388447==   total heap usage: 3 allocs, 4 frees, 73,738 bytes allocated
==3388447== 
==3388447== All heap blocks were freed -- no leaks are possible
==3388447== 
==3388447== For lists of detected and suppressed errors, rerun with: -s
==3388447== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

【讨论】:

    猜你喜欢
    • 2010-09-16
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 2012-01-30
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    相关资源
    最近更新 更多