This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/ARM-CGT: deque::push_back causes FaultISR on structures over 64 bytes. Compiler bug?

Part Number: ARM-CGT
Other Parts Discussed in Thread: TM4C1294NCPDT, EK-TM4C1294XL

Tool/software: TI C/C++ Compiler

I am using c++ compiler TI v18.1.5.LTS with TM4C1294NCPDT compiling with c++14 mode. Stack size set to 16384, heap set to 120000.

It appears any 2nd attempt to add a structure of size > 64 bytes will cause a FaultISR

Relevant code example:

#include <deque>

struct s {
	char d[65];
};

int main()
{
	int size = sizeof(s);
	
	std::deque<s> test;
	test.push_back(s());
	test.push_back(s()); // will crash here

	while (1){}
}

Structures of 64 bytes or less appears to work properly.

Digging in to it a bit more... looks like the problem stems in the push_back function.

Inside the push_back function is:

    if (__back_spare() == 0)
        __add_back_capacity();
    // __back_spare() >= 1
    __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), __v);

On the 2nd push_back attempt, the if condition is not satisifed so it does not call __add_back_capacity()

Then, addressof() function returns an invalid memory address... which ends up calling placement new at an invalid memory address causing the crash.

If this is not the correct forum for this issue, please direct me to the proper place.

Thank you.

  • Update:
    It appears when I add a 65 byte structure to the deque, __back_spare() returns -1, thus, it does not add any capacity.
  • I am unable to reproduce the problem.  I'd appreciate if you would submit your CCS project.  Please follow the directions in the article Sharing Projects to create the zip file, then attach it to your next post.

    Thanks and regards,

    -George

  • ZIP of my project should be attached. I am using the Debug profile.

    FYI, I compiled and executed with 16.9.7 LTS and did not have any issue.

    More information I have found while debugging. __back_spare() is returning -1, because capacity() is returning 0, even though an item is in the container.

    A notable difference when having a struct of size 65 vs a size of 64, the __block_size is set to 1 instead of 2, causing capacity() to return 0 when one item is added.

    I may be able to get around this issue by calling resize(size() +1) instead of push_back.

    Is this issue more appropriate to be discussed in LLVM forums?

    test_deque.zip

  • Something also interesting: I get a different result of __capacity() whether I use push_back or resize().

    See the code comments for the result

    #define protected public
    #define private public
    #include <deque>
    
    struct s {
    	char d[65];
    };
    
    int main()
    {
    	{
    		std::deque<s> test;
    		test.resize(test.size()+1, s());
    		int back_spare = test.__back_spare(); // 0
    		int cap = test.__capacity(); // 1
    		test.resize(test.size()+1, s()); // just fine
    	}
    	{
    		std::deque<s> test;
    		test.push_back(s());
    		int back_spare = test.__back_spare(); // -1
    		int cap = test.__capacity(); // 0
    		test.push_back(s()); // crash
    	}
    
    	while (1){}
    }
    

  • Another update:

    It appears that I can call resize(1) on the first entry, then can call push_back and everything will be fine.

    Resize ends up calling __add_back_capacity(1) while push_back calls __add_back_capacity()

    The difference appears to be that __add_back_capacity(1) allocates an extra block if the deque is empty.

    Line 2483 of deque:

    size_type __nb = __recommend_blocks(__n + __base::__map_.empty());

    Any ideas for the proper fix?

  • Thank you for submitting your project.  Unfortunately, I am still unable to reproduce the problem.

    I don't have the same hardware.  So I had to adapt your project to run on an MSP432 launchpad.  It has the same ARM CPU core. I use same version of the compiler.  The critical build options are the same.  

    I set a breakpoint at the start of the final while (1) loop.  I can always run to it with no problem.  I presume this means it works for me.

    Your project, as supplied, uses the Debug_GNU build configuration.  This build configuration uses the GNU ARM compiler.  I changed the configuration to Debug, which uses the TI ARM compiler.

    At this point, I have to suspect your problem is caused by some obscure difference in the hardware.  If that is the case, I lack the expertise to find the problem.  I will ask others, who may have matching hardware, or at least something that is much closer, to attempt to reproduce the problem.

    This next question exposes my lack of expertise in hardware.  On MSP432, there is a watchdog timer which, in example projects like these, is always turned off.  Might your problem be caused by failing to turn off the watchdog timer?

    Thanks and regards,

    -George

  • Thank you for looking at it. That is unfortunate you are unable to recreate. I can assure you its not a watchdog issue.

    I am surprised you are unable to recreate with the same compiler configuration. I doubt it is hardware related. Can you confirm your ti-cgt-arm_18.1.5.LTS/lib/src/libcxx/deque file contains the lines (266-270):

    template <class _ValueType, class _DiffType>
    struct __deque_block_size {
      enum __attribute__((__packed__)) { _MAX_BYTES = 32 * sizeof(void*) };
      static const _DiffType value = sizeof(_ValueType) < _MAX_BYTES ? (_MAX_BYTES / sizeof(_ValueType)) : 1;
    };

    And also contains lines (1820-1830):

    template <class _Tp, class _Allocator>
    void
    deque<_Tp, _Allocator>::push_back(value_type&& __v)
    {
        allocator_type& __a = __base::__alloc();
        if (__back_spare() == 0)
            __add_back_capacity();
        // __back_spare() >= 1
        __alloc_traits::construct(__a, _VSTD::addressof(*__base::end()), _VSTD::move(__v));
        ++__base::size();
    }

  • A colleague is able to reproduce the issue. He runs it on a EK-TM4C1294XL Launchpad. Is this what you run it on? Based on that, I filed the entry CODEGEN-6130 in the SDOWP system. You are welcome to follow it with the SDOWP link below in my signature.

    Jason MacDonald said:
    Can you confirm your ti-cgt-arm_18.1.5.LTS/lib/src/libcxx/deque file contains the lines

    Yes to both.

    Thanks and regards,

    -George

  • Yes I am using  EK-TM4C1294XL

    Thank you for filing a bug report.