나는 런타임시 segfault해야한다는 다음과 같은 생각을 썼다. 그러나 그렇지 않습니다. 정상적으로 실행되며 이유를 이해할 수 없습니다.게재 위치는 어떻게 새로 작동합니까?
#include <cstdlib>
#include <cstdio>
#include <new>
struct MyStruct
{
double *a;
MyStruct()
: a(NULL)
{ printf("Default constructor\n"); }
MyStruct(double *b)
: a(b)
{}
MyStruct(const MyStruct& other)
{
printf("Copy-constructor\n");
if (a != NULL && *a != 3.14)
a = other.a;
}
};
int main()
{
double num = 3.14;
MyStruct obj(&num);
void *ptr = ::operator new(sizeof(MyStruct));
new (ptr) MyStruct(obj);
delete (MyStruct*) ptr; // Calls ~MyStruct
}
출력은 다음과 같습니다
Copy-constructor
내가 void *ptr = ::operator new(sizeof(MyStruct));
을 쓸 때 나는이 전용 메모리를 할당 알고, 기본 생성자를 호출하지 않아야합니다. 그리고 그것은 다음과 같이 보이지 않습니다.
내가 new (ptr) MyStruct(obj);
이라고 쓸 때, 내가 생각한 것처럼 작동한다면 segfault로 예상 할 수 있습니다. 나는 이것이 ((MyStruct*) ptr)->MyStruct(obj)
과 같다고 생각한다. a
이 초기화되지 않았기 때문에 if (a != NULL && *a != 3.14)
줄은 *a != 3.14
에 도달하고 segfault에 도달해야합니다.
내 문제는 a
이 초기화되지 않은 것 같습니다 ("기본 생성자"출력이 없었기 때문에). 그러나 이전에는 여전히 segfault가 아닙니다. 내가 뭘 놓치고 있니?
.file "placement_new.cpp"
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LCPI0_0:
.quad 4614253070214989087 # double 3.1400000000000001
.text
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0:
push rbp
.Ltmp2:
.cfi_def_cfa_offset 16
.Ltmp3:
.cfi_offset rbp, -16
mov rbp, rsp
.Ltmp4:
.cfi_def_cfa_register rbp
sub rsp, 48
lea rdi, qword ptr [rbp - 24]
lea rsi, qword ptr [rbp - 16]
movsd xmm0, qword ptr [.LCPI0_0]
mov dword ptr [rbp - 4], 0
movsd qword ptr [rbp - 16], xmm0
call _ZN8MyStructC2EPd
movabs rdi, 8
call _Znwm
mov qword ptr [rbp - 32], rax
mov rax, qword ptr [rbp - 32]
cmp rax, 0
mov qword ptr [rbp - 40], rax # 8-byte Spill
je .LBB0_2
# BB#1:
lea rsi, qword ptr [rbp - 24]
mov rax, qword ptr [rbp - 40] # 8-byte Reload
mov rdi, rax
call _ZN8MyStructC2ERKS_
.LBB0_2:
mov rax, qword ptr [rbp - 32]
cmp rax, 0
mov qword ptr [rbp - 48], rax # 8-byte Spill
je .LBB0_4
# BB#3:
mov rax, qword ptr [rbp - 48] # 8-byte Reload
mov rdi, rax
call _ZdlPv
.LBB0_4:
mov eax, dword ptr [rbp - 4]
add rsp, 48
pop rbp
ret
.Ltmp5:
.size main, .Ltmp5-main
.cfi_endproc
.section .text._ZN8MyStructC2EPd,"axG",@progbits,_ZN8MyStructC2EPd,comdat
.weak _ZN8MyStructC2EPd
.align 16, 0x90
.type _ZN8MyStructC2EPd,@function
_ZN8MyStructC2EPd: # @_ZN8MyStructC2EPd
.cfi_startproc
# BB#0:
push rbp
.Ltmp8:
.cfi_def_cfa_offset 16
.Ltmp9:
.cfi_offset rbp, -16
mov rbp, rsp
.Ltmp10:
.cfi_def_cfa_register rbp
mov qword ptr [rbp - 8], rdi
mov qword ptr [rbp - 16], rsi
mov rsi, qword ptr [rbp - 8]
mov rdi, qword ptr [rbp - 16]
mov qword ptr [rsi], rdi
pop rbp
ret
.Ltmp11:
.size _ZN8MyStructC2EPd, .Ltmp11-_ZN8MyStructC2EPd
.cfi_endproc
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LCPI2_0:
.quad 4614253070214989087 # double 3.1400000000000001
.section .text._ZN8MyStructC2ERKS_,"axG",@progbits,_ZN8MyStructC2ERKS_,comdat
.weak _ZN8MyStructC2ERKS_
.align 16, 0x90
.type _ZN8MyStructC2ERKS_,@function
_ZN8MyStructC2ERKS_: # @_ZN8MyStructC2ERKS_
.cfi_startproc
# BB#0:
push rbp
.Ltmp14:
.cfi_def_cfa_offset 16
.Ltmp15:
.cfi_offset rbp, -16
mov rbp, rsp
.Ltmp16:
.cfi_def_cfa_register rbp
sub rsp, 32
lea rax, qword ptr [.L.str]
mov qword ptr [rbp - 8], rdi
mov qword ptr [rbp - 16], rsi
mov rsi, qword ptr [rbp - 8]
mov rdi, rax
mov al, 0
mov qword ptr [rbp - 24], rsi # 8-byte Spill
call printf
mov rsi, qword ptr [rbp - 24] # 8-byte Reload
cmp qword ptr [rsi], 0
mov dword ptr [rbp - 28], eax # 4-byte Spill
je .LBB2_3
# BB#1:
movsd xmm0, qword ptr [.LCPI2_0]
mov rax, qword ptr [rbp - 24] # 8-byte Reload
mov rcx, qword ptr [rax]
movsd xmm1, qword ptr [rcx]
ucomisd xmm1, xmm0
jne .LBB2_2
jp .LBB2_2
jmp .LBB2_3
.LBB2_2:
mov rax, qword ptr [rbp - 16]
mov rax, qword ptr [rax]
mov rcx, qword ptr [rbp - 24] # 8-byte Reload
mov qword ptr [rcx], rax
.LBB2_3:
add rsp, 32
pop rbp
ret
.Ltmp17:
.size _ZN8MyStructC2ERKS_, .Ltmp17-_ZN8MyStructC2ERKS_
.cfi_endproc
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "Copy-constructor\n"
.size .L.str, 18
.ident "Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)"
.section ".note.GNU-stack","",@progbits
릴리스 버전을 컴파일하고 다시 시도하십시오. – Matt
'내가 무엇을 놓치고 있니? 'C++에서 열악한 일을 할 때 프로그램이 중단된다는 것을 의미하지 않는다는 단순한 사실을 놓치고 있습니다. – PaulMcKenzie
이 코드에는 정의되지 않은 동작이 있습니다. 즉, 'delete'가 없으며 'new'라는 배치로 생성 된 객체입니다. 그것을 파괴하고 메모리를 따로 분리해야합니다 :'mptr-> ~ MyStruct(); operator delete (ptr);'(여기서'mptr'은'new'에서 반환 된 MyStruct *입니다). –