移动构造函数和分段错误

时间:2017-05-26 19:47:25

标签: c++

我有一个结构X,它包含一个指向数组的指针:

int global_id = 0;

struct X
{
        int id; 
        char *p; 

        X(int id_) : p(new char[1024]), id(id_)
        {   
                printf("Constructing X (id %d)\n", id);
        }   

        X() : p(new char[1024]), id(global_id++)
        {   
                printf("Constructing X (id %d)\n", id);
        }   

        ~X()
        {   
                delete [] p;
                printf("Destroying X (id %d) and array\n", id);
        }   

        X(X const & rhs) : id(global_id++)
        {   
                printf("X copy constructor (%d -> new %d) \n", rhs.id, id);
                memcpy(p, rhs.p, sizeof(p));
        }   

        X& operator=(X const & rhs)
        {   
                printf("X copy assignment (%d -> %d) \n", rhs.id, id);
                memcpy(p, rhs.p, sizeof(p));
        }   

        X(X && rhs) : id(global_id++)
        {   
                printf("X move constructor (%d -> new %d) \n", rhs.id, id);
                swap(p, rhs.p);
        }   

        X& operator=(X && rhs)
        {   
                printf("X move assignment (%d -> %d) \n", rhs.id, id);
                swap(p, rhs.p);
        }   

};

我创建了一个函数foo(),它构造一个本地X并返回它。但它导致了一个段错误:

X foo()
{
        X local_x;
        return local_x;
}

main()
{
        printf("\n1\n");
        X x;

        printf("\n2\n");
        x = foo();
}

我的期望是: 1)构造local_x,打印"构造X(id 1)"

2)将local_x移动到要返回的临时对象中,打印" X移动构造函数(1 - > new 2)"

3)local_x被销毁,打印"销毁X(id 1)"

4)临时移动到x,打印" X移动分配(2 - > 0)"

相反,在local_x的析构函数中发生了段错误:

(gdb) bt
#0  0x00007ffff74ab428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff74ad02a in __GI_abort () at abort.c:89
#2  0x00007ffff74ed7ea in __libc_message (do_abort=do_abort@entry=2, 
    fmt=fmt@entry=0x7ffff76062e0 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007ffff74f9ae8 in malloc_printerr (ar_ptr=0x0, ptr=<optimized out>, 
    str=0x7ffff7606308 "munmap_chunk(): invalid pointer", action=<optimized out>)
    at malloc.c:5004
#4  munmap_chunk (p=<optimized out>) at malloc.c:2840
#5  __GI___libc_free (mem=<optimized out>) at malloc.c:2961
#6  0x0000000000400c8d in X::~X (this=0x7fffffffe220, __in_chrg=<optimized out>)
    at ref.cpp:27
#7  0x000000000040098e in foo () at ref.cpp:59
#8  0x0000000000400a4c in main () at ref.cpp:86
(gdb) f 6
#6  0x0000000000400c8d in X::~X (this=0x7fffffffe220, __in_chrg=<optimized out>)
    at ref.cpp:27
27                      delete [] p;
(gdb) p id
$1 = 1

以下内容打印到stdout:

1
Constructing X (id 0)
2
Constructing X (id 1)
X move constructor (1 -> new 2) 
*** Error in `/home/spm/code/ref': munmap_chunk(): invalid pointer: 0x0000000000400edd ***

为什么我会遇到段错误? p应该是指向临时构造函数中使用new []分配的数组的指针,因此delete []应该可以正常工作。

1 个答案:

答案 0 :(得分:0)

您的复制构造函数和移动构造函数在其初始化列表中没有python -m pip install SomePackage==3.6.1 # specific version python -m pip install "SomePackage>=1.0.4" # minimum version ,使它们保持未初始化状态。对于你的拷贝构造函数,这意味着你p一堆字节到内存中的某个随机点,这是未定义的。对于您的移动构造函数,这意味着当您memcpy时,您将swap置于未初始化状态,然后rhs.p

对于您的复制构造函数,您可能希望像调用默认构造函数一样调用delete[]。对于移动构造函数,不需要分配内存;您只需将new初始化为pnullptr即可安全)。