Teensy 4.0 - Why is this code crashing Teensy?

ghostintranslation

Well-known member
Hi,

I'm working on a fairly large project in which I created derived classes from AudioStream. I started to see my Teensy crash while running. I managed to reproduce the issue in a much smaller piece of code:

Code:
// project.ino


#include <Audio.h>
#include "CustomStream.h"

AudioOutputI2S           i2s1; 

void setup() {
  
  Serial.begin(115200);

  // Wait for serial monitor
  while (!Serial && millis() < 2500); 
  
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(10);

  
  AudioSynthWaveformModulated* sine = new AudioSynthWaveformModulated();
  sine->begin(WAVEFORM_SINE);
  sine->frequency(0.5);
  sine->amplitude(0.1);
  
  CustomStream* stream1 = new CustomStream("stream1");
  stream1->setOnChange(onChange);
  CustomStream* stream2 = new CustomStream("stream2");
  stream2->setOnChange(onChange);
  CustomStream* stream3 = new CustomStream("stream3");
  stream3->setOnChange(onChange);

  AudioConnection* patchCord1 = new AudioConnection(*sine, 0, *stream1, 0);
  AudioConnection* patchCord2 = new AudioConnection(*sine, 0, *stream2, 0);
  AudioConnection* patchCord3 = new AudioConnection(*sine, 0, *stream3, 0);
  
}

void onChange(String name, float val, float diff){
  Serial.print("onChange ");
  Serial.print(name);
  Serial.print(" ");
  Serial.println(val);
}

void loop() {
Serial.println("loop");
}

Code:
// CustomStream.h

#ifndef CustomStream_h
#define CustomStream_h

#include "AudioStream.h"
#include <vector>

using ChangeCallback = void (*)(String name, float value, float diff);

class CustomStream : public AudioStream
{
public:
    CustomStream(String name);
    void update(void);
    void setOnChange(ChangeCallback fptr);

private:
        audio_block_t *inputQueueArray[1];
        
         // Change callback function
         ChangeCallback changeCallback = nullptr;

         float value = 0;

         String name = "";
         
};

inline CustomStream::CustomStream(String name) : AudioStream(1, inputQueueArray)
{
  // Set to always active so update() is called even without patchcord connected
  this->active = true;

  this->name = name;
}
inline void CustomStream::update()
{
  Serial.println("update 1");
  
  if (this->changeCallback != nullptr)
  {
  Serial.println("update 2");
    this->changeCallback(this->name, this->value, 0);
  }

  // Set the target from the input
    audio_block_t *block;
    uint32_t *p, *end;
 
    block = receiveReadOnly(0);
    if (block){
      this->value = block->data[0]; // TODO: instead of using one value and dropping the 127 others, drop 1
      release(block);
    }

    
    block = allocate();
    if (block){
      p = (uint32_t *)(block->data);
      end = p + AUDIO_BLOCK_SAMPLES/2;
      do {
        *p++ = this->value;
        *p++ = this->value;
        *p++ = this->value;
        *p++ = this->value;
        *p++ = this->value;
        *p++ = this->value;
        *p++ = this->value;
        *p++ = this->value;
      } while (p < end);
      transmit(block, 0);
      release(block);
    }
}

inline void CustomStream::setOnChange(ChangeCallback changeCallback)
{
    this->changeCallback = changeCallback;
}
#endif

That program always end up crashing with a serial output like this:
Code:
)))))))))))))))))))))))L T \ d l t | � � � � � � � � � � � �                            ����� �V  �
   �U  �U      $ $ , , 4 4 < < D D L L T T \ \ d d l l t t | | � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �         $ $ , , 4 4 < < D D L L T T \ \ d d l l t t | | � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 
 
 
 
 
 
 
 
 $
 $
 ,
 ,
 4
 4
 <
 <
 D
 D
 L
 L
 T
 T
 \
 \
 d
 d
 l
 l
 t
 t
 |
 |
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
         $ $ , , 4 4 < < D D L L T T \ \ d d l l t t | | � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � @S  x D HS  �@� 	=�bC/:m*_�Bm�]68`! �%@ ���
  ]  �-  �=  �M  ` ���  �  �/  �?  �O  � ���  �!  �1  �A  �Q  � ���  �#  �3  �C  �S  � ���  �%  �5  �E  �U  ���  �'  �7  �G  �W  � ���!  �1  �A  �Q  �a  � ���#  �3  �C  �S  �c   ���%  �5  �E  �U  �e    ���'  �7  �G  �W  �g  @ ���)  �9  �I  �Y  �i  ` ���+  �;  �K  �[  �k  � ���-  �=  �M  �]  �m  ���/  �?  �O  �_  �o   �9  �E  �Q  �a  �q  @ ��9  �I  �Y  �i  �y  @ �I  �U  �a  �q  ��  ��I  �Y  �i  �y  ��  �, �  ���,���Q  �a  �q  ��  ��  ����Q  �a  �q  ��  ��  ���` `' `7 `G `W ���&&&&&&&&&&&&&&m@q@%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&�&&&&&&}<&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&�(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&� % �2 �B �R �

which is not very helpful.

I am thinking it could be 2 things, either too many Serial.print, or I do something too expensive for the RAM, but in that case what is it?

In my original project I was getting this output:
Code:
basic_string::_M_construct null not validbasic_string::basic_stringstring::stringbasic_string::substr*N12_GLOBAL__N_121system_error_categoryE*N12_GLOBAL__N_122generic_error_categoryE< �h�h�h�h�i�h�i�h �h�h�h�h�i�h�i�h�   � �
 �
 genericsystemNSt3_V214error_categoryE� T
 �
 \ 9jMj1j� x  std::bad_allocSt9bad_alloc� �j�j�x�x5kij�j�j�j� � 
 N10__cxxabiv117__class_type_infoEN10__cxxabiv115__forced_unwindE� � � x N10__cxxabiv119__foreign_exceptionEstd::exceptionstd::bad_exception�  � ]oioaoSt9exceptionSt13bad_exception� �  � �w�w�x�x5kij�x�wEx� � � N10__cxxabiv120__si_class_type_infoE� 
 St9type_info� ,
  St11logic_error 
 �x%y�xSt12length_error� P
  
 d
 9yMy�xbasic_string::_S_createbasic_string::resizebasic_string::_S_construct null not valid/dev/urandomdefault/dev/randomrandom_device::random_device(const std::string&)rbmt19937terminate called recursively
terminate called after throwing an instance of ''
terminate called without an active exception
  what():  tT T a, , < 	bH H \ sl x F\ i� � 1 
o $ 1X 
dh 
x 2� � � � � � � � � � � � � � 
� 
� 
� 
    �% �%   
  
0 0 < < P P X X h h 	p � x 	�% � � � � � 	� 	� 	� 	� 
� 
� � � � � � � � � � � � �   � � � � � � � � � 
4 �         	( , < @ D H P T 8 � X \ ` d h l p t �! x  l |   � � � �" � ` � � � � � � � � � � � � @ � � � � � � 8
 � � � � � � � � � L#           $  < ( @ , 0 4 8 < @ D X \ ` d h l � x � x � � � � _GLOBAL_(anonymous namespace)cldtptqustring literalstdautoli[abi:::{default arg#%d}::JArray[]vtable for VTT for construction vtable for -in-typeinfo for typeinfo name for typeinfo fn for non-virtual thunk to covariant return thunk to java Class for guard variable for TLS init function for TLS wrapper function for reference temporary #hidden alias for non-transaction clone for _Sat _Accum_Fract, operatoroperator adgs>(ix : new ulllullfalsetruejava resource decltype (this{parm#global constructors keyed to global destructors keyed to {lambda()#{unnamed type# [clone  restrict volatile const&&complex imaginary ::* __vector(std::allocatorallocatorstd::basic_stringbasic_stringstd::stringstd::basic_string<char, std::char_traits<char>, std::allocator<char> >std::istreamstd::basic_istream<char, std::char_traits<char> >basic_istreamstd::ostreamstd::basic_ostream<char, std::char_traits<char> >basic_ostreamstd::iostreamstd::basic_iostream<char, std::char_traits<char> >basic_iostreamaN&=aS=aa&anatalignof azccconst_cast()cm,co~dV/=dadelete[] dcdynamic_castde*dldelete ds.*dv/eO^=eo^eq==>=gtlS<<=<=operator"" ls<<lt<mI-=mL*=mi-mlmm--nanew[]ne!=nt!nwnewoR|=oo|||pL+=pl+pm->*pp++ps->?rM%=rS>>=rcreinterpret_castrm%rs>>scstatic_castsizeof sztrthrowtwthrow signed charboolbooleancharbytedoublelong doublefloat__float128unsigned charintunsigned intunsignedunsigned long__int128unsigned __int128shortunsigned shortvoidwchar_tlong longunsigned long longdecimal32decimal64decimal128halfchar16_tchar32_tdecltype(nullptr)         (((((                  �AAAAAABBBBBB 0( CPOSIXSuccessNot ownerNo such file or directoryNo such processInterrupted system callI/O errorNo such device or addressArg list too longExec format errorSocket already connectedBad file numberNo childrenDestination address requiredNo more processesNot enough spacePermission deniedBad addressDevice or resource busyFile existsCross-device linkNo such deviceNot a directoryHost is downConnection already in progressIs a directoryInvalid argumentNetwork interface is not configuredConnection aborted by networkToo many open files in systemFile descriptor value too largeNot a character deviceText file busyFile too largeHost is unreachableNo space left on deviceNot supportedIllegal seekRead-only file systemToo many linksBroken pipeMathematics argument out of domain of functionResult too largeNo message of desired typeIdentifier removedIllegal byte sequenceDeadlockNetwork is unreachableNo lockNot a streamStream ioctl timeoutNo stream resourcesVirtual circuit is goneProtocol errorUnknown protocolMultihop attemptedBad messageFunction not implementedDirectory not emptyFile or path name too longToo many symbolic linksNo buffer space availableNo dataAddress family not supported by protocol familyProtocol wrong type for socketSocket operation on non-socketProtocol not availableConnection refusedConnection reset by peerAddress already in useAddress not availableSoftware caused connection abortSocket is not connectedSocket is already connectedOperation canceledState not recoverablePrevious owner diedOperation not supported on socketValue too large for defined data typeMessage too longConnection timed out0000000000000000INFNAN0123456789ABCDEF0123456789abcdef(null)0                InfinityNaN�?$@Y@@�@��@j�@��.A�cA�חAe��A _�B�vH7B��mB@�0�B�ļ�B4&�kC��7y�AC�؅W4vC�Ngm��C=�`�X�C@��x�DP����KD��M���D�J��-�D���yCx�D��7y�ACn����F��?�O8M20�Hw�Z<�s�Ou}:@� ����������F�#p  @��y6737280�T ��
 �
 v�}+ �+ �+ 3ͫ4m���|) 	)������������������������h�h2 42 @2 T2 \2 d2 l2 t2 |2 �2 �2 �2 �2 �2 �2 �2 �2 �2 �2 �2 �2 3 3 3 3  3 $(  ( l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' l' ������0( CCCCCCCI%��� � ( ( ( ( ( ( ( ( ( ��������������ASCIIASCII�`  �- �- �- `  �_  �- �- �- �- �- �- �- �- . . . . . . . .  .  . (. (. 0. 0. 8. 8. @. @. H. H. P. P. X. X. `. `. h. h. p. p. x. x. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. �. / / / / / / / /  /  / (/ (/ 0/ 0/ 8/ 8/ @/ @/ H/ H/ P/ P/ X/ X/ `/ `/ h/ h/ p/ p/ x/ x/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ �/ 0 0 0 0 0 0 0 0  0  0 (0 (0 00 00 80 80 @0 @0 H0 H0 P0 P0 X0 X0 `0 `0 h0 h0 p0 p0 x0 x0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 �0 1 1 1 1 1 1 1 1  1  1 (1 (1 01 01 81 81 @1 @1 H1 H1 P1 P1 X1 X1 `1 `1 h1 h1 p1 p1 x1 x1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 �1 @S  �`  � $2 @]  HS  HS  �`  �`  �`  `  `  `  ��,�@$ 	=3�D:m�_�Bm�R8`! �%@6 ���
  �  �-  �=  �M  `6 ���  �  �/  �?  �O  �6 ���  �!  �1  �A  �Q  �6 ���  �#  �3  �C  �S  �6 ���  �%  �5  �E  �U  ���  �'  �7  �G  �W  �7 ���!  �1  �A  �Q  �a  �7 ���#  �3  �C  �S  �c  8 ���%  �5  �E  �U  �e   8 ���'  �7  �G  �W  �g  @8 ���)  �9  �I  �Y  �i  `8 ���+  �;  �K  �[  �k  �8 ���-  �=  �M  �]  �m  ���/  �?  �O  �_  �o  9 ��1  �A  �Q  �a  �q   9 ��9  �I  �Y  �i  �y  ��A  �Q  �a  �q  ��  �8 �A  `W  �i  �y  ��  M2 �  M��,���Q  �a  �q  ��  ��  ����Q  �a  �q  ��  ��  ���`: `J `Z `j `z XS  XS  �	����A�A�A�A�A�A�A�A�A�A�A�A�A�A)\-\��A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�B�A�A�A�A�A9X�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�D�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�@�S �5 G P ` p ! @�S � "�7 ���!  �0  @  P  `  �7 �8 eQ@9 �8 ��I  `W  `

which does say more but also not really...

I really want to overcome this issue but I don't see what I'm doing wrong?
 
Quick look, shouldn't variable names be defined globally? sine, patchCord1 , patchCord2, patchCord3 ? outside of the setup?

so always there and not blasted afterwards by memory manager over writting it? Since it looks like in one of your outputs, its dumping random memory?

As once out of setup, those variables are now out of scope?
 
What happens if you remove Serial.println("loop"); so you're printing only from the interrupt and not also from the main program?
 
Quick look, shouldn't variable names be defined globally? sine, patchCord1 , patchCord2, patchCord3 ? outside of the setup?

so always there and not blasted afterwards by memory manager over writting it? Since it looks like in one of your outputs, its dumping random memory?

As once out of setup, those variables are now out of scope?

Those are just objects that can be instantiated anywhere, outside setup, in the setup, in a function, in a class. I've done that for a while without any issue.

If the variables were out of scope it would throw an error right at compile time.

What happens if you remove Serial.println("loop"); so you're printing only from the interrupt and not also from the main program?

Indeed in this example it does not crash if I remove this Serial.println("loop") . But I tried on my original project to remove all prints and it still crashes.
I've tried to reduce my original project but I can't seem to reproduce then... So I can't find what's the issue in there...

Here View attachment 26798 is the project that produces the issue. There is 10 classes but I commented so many things that I think it's not that big. It doesn't require any hardware, just the Teensy alone is enough to reproduce the issue.

When you run this code, it will print some stuff and you'll see the LED also on but not very bright. When it crashes it stops printing and the LED goes off.

You can deactivate the prints by commenting Motherboard.setDebug(true); in the main file.

Basically, I created classes that derive from AudioStream, ALed, ADac and APotentiometer, they actually not derive directly from AudioStream I split it in a few classes. With the appropriate hardware this code allows to read potentiometers, control LEDs and DACs outputs, also connect those to the Audio lib objects.
More technically and good to know:
- the ALed and APotentiometer and ADac self register in the AIO vectors.
- the IOManager handles the hardware to read/write using the SPI channel.

I had it working without crashing before I start deriving from AudioStream, so I'm wondering if there is something there that I do wrong, and that seem to mean that the other part of it is ok but also if that's a memory leak somewhere it could just be triggered now for whatever reason while it was there already before so I can't be sure really.

I'd appreciate it very much if you can have a look at this code and at least point me to some possible issues, I know it might not be easy to debug though.

Thanks
 
Sorry,

Busy debugging some other stuff...

When you say Crashing... Are you saying that the program crashes and restarts?

With T4.x you at times capture some debug information, by using the Crashreport...

Like:
Code:
void setup()
{

  // Open serial communications and wait for port to open
  while (!Serial && millis() < 5000) ;

  if (CrashReport) Serial.print(CrashReport);
...

Also I don't use audiostream or the like... So probably not much help.

Good luck
 
By crashing I mean that it freezes during execution, it stops running, but it does not restart.

Ah I was not aware about CrashReport, I see this is in 1.54, I am using 1.53 at the moment, but I could try upgrading.
 
I think I may have find what it was but I can't be too sure yet, it's hard to be sure because it would stop happening when commenting out some code but then commenting out another piece instead would produce the same result and those things have nothing in common, which makes me think there is something happening in the memory.

So I replaced my 3 vectors by arrays that I re instantiate when self registering a new input/output/led by copying the old to the new +1, and the freezing is not happening now.

I read that vectors could be of potential memory issues, could that be the case here?
 
Back
Top