Good day. There is something like this:

typedef std::map< unsigned int, Signal > SMap; void thread_proc( ) { try { for( ; ; ) { std::vector< SMap > signals; /// { boost::mutex::scoped_lock lock( m_mutex ); m_signalMaps.swap( signals ); } BOOST_FOREACH( const auto& signal, signals ) HandleSignalMaps( signal ); } //Далее будет указан дизассемблированный код этого участка программы } catch( const boost::thread_interrupted& ) { } 

}

Trying to watch his disassembled version. I noticed the following fact: In Release and Debug, the code is distinguished by calling delete.

Release:

 rcx,qword ptr [signals] 000007FECFF71902 test rcx,rcx 000007FECFF71905 je thread_proc+1CBh (07FECFF7191Bh) 000007FECFF71907 mov rdx,qword ptr [rsp+30h] 000007FECFF7190C call std::vector<std::map<unsigned int,Signal,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,Signal> > >,std::allocator<std::map<unsigned int,Signal,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,Signal> > > > >::_Destroy (07FECFF71BF0h) 000007FECFF71911 mov rcx,qword ptr [signals] 000007FECFF71916 call operator delete (07FECFFBCDF4h) // Вот этот оператор 000007FECFF7191B mov qword ptr [signals],r12 000007FECFF71920 mov qword ptr [rsp+30h],r12 000007FECFF71925 mov qword ptr [rsp+38h],r12 000007FECFF7192A jmp thread_proc+40h (07FECFF71790h) 

Debug:

 000007FECCC44A09 lea rcx,[rsp+28h] 000007FECCC44A0E call std::vector<std::map<unsigned int,Signal,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,Signal> > >,std::allocator<std::map<unsigned int,Signal,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,Signal> > > > >::~vector<std::map<unsigned int,Signal,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,Signal> > >,std::allocator<std::map<unsigned int,Signal,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,Signal> > > > > (07FECCB06226h) 000007FECCC44A13 jmp thread_proc+30h (07FECCC44510h) 

I understand, in the release delete, it tries to delete the local vector 'signals'. But why is this not in Debug? And unless local variables are deleted call delete? I assumed there would be a pop call, since memory should have been allocated on the stack. Explain, please, where I am mistaken in reasoning.

    1 answer 1

    Not sure about the correctness.

    The internal array of vector cannot be allocated entirely on the stack, since The limit on the size of the variable in the stack is about 4MB (by default), and the vector can be 100MB or more. Those. in fact, vector is a wrapper over a dynamic array. When deleting an object of class vector we must delete its dynamic array in the destructor. Further the compiler can inline a call as wants.

    Try to make a minimal example of working with a vector and deleting it, for example:

     void test() { vector<int> P; P.resize(10000); } 

    No optimization

     test(): pushq %rbp movq %rsp, %rbp pushq %rbx subq $40, %rsp leaq -48(%rbp), %rax movq %rax, %rdi call std::vector<int, std::allocator<int> >::vector() leaq -48(%rbp), %rax movl $10000, %esi movq %rax, %rdi call std::vector<int, std::allocator<int> >::resize(unsigned long) leaq -48(%rbp), %rax movq %rax, %rdi call std::vector<int, std::allocator<int> >::~vector() jmp .L4 movq %rax, %rbx leaq -48(%rbp), %rax movq %rax, %rdi call std::vector<int, std::allocator<int> >::~vector() movq %rbx, %rax movq %rax, %rdi call _Unwind_Resume 

    Clearly visible designer and destruktor

    -O2 :

     test(): subq $8, %rsp movl $40000, %edi call operator new(unsigned long) leaq 40000(%rax), %rcx movq %rax, %rdx .L2: movl $0, (%rdx) addq $4, %rdx cmpq %rcx, %rdx jne .L2 movq %rax, %rdi addq $8, %rsp jmp operator delete(void*) 

    The vector is replaced with a dynamic array (inline).

    asm code was generated here https://gcc.godbolt.org/

    I think in your case the compiler was able to optimize the code in the release.