5

I have been working for a couple of days on a problem with my application running on an embedded Arm Linux platform. Unfortunately the platform precludes me from using any of the usual useful tools for finding the exact issue. When the same code is run on the PC running Linux, I get no such error.

In the sample below, I can reliably reproduce the problem by uncommenting the string, list or vector lines. Leaving them commented results in the application running to completion. I expect that something is corrupting the heap, but I cannot see what? The program will run for a few seconds before giving a segmentation fault.

The code is compiled using a arm-linux cross compiler:

arm-linux-g++ -Wall -otest fault.cpp -ldl -lpthread
arm-linux-strip test

Any ideas greatly appreciated.

#include <stdio.h>
#include <vector>
#include <list>
#include <string>

using namespace std;
/////////////////////////////////////////////////////////////////////////////

class TestSeg
{
 static pthread_mutex_t     _logLock;

 public:
  TestSeg()
  {
  }

  ~TestSeg()
  {
  }

  static void* TestThread( void *arg )
  {
   int i = 0;
   while ( i++ < 10000 )
   {
    printf( "%d\n", i );
    WriteBad( "Function" );
   }
   pthread_exit( NULL );
  }

  static void WriteBad( const char* sFunction )
  {
   pthread_mutex_lock( &_logLock );

   printf( "%s\n", sFunction );
   //string sKiller;     //       <----------------------------------Bad
   //list<char> killer;    //       <----------------------------------Bad
   //vector<char> killer;    //       <----------------------------------Bad

   pthread_mutex_unlock( &_logLock );
   return;
  }

  void RunTest()
  {
   int threads = 100;
   pthread_t     _rx_thread[threads];
   for ( int i = 0 ; i < threads ; i++ )
   {
    pthread_create( &_rx_thread[i], NULL, TestThread, NULL );
   }

   for ( int i = 0 ; i < threads ; i++ )
   {
    pthread_join( _rx_thread[i], NULL );
   }
  }

};

pthread_mutex_t       TestSeg::_logLock = PTHREAD_MUTEX_INITIALIZER;


int main( int argc, char *argv[] )
{
 TestSeg seg;
 seg.RunTest();
 pthread_exit( NULL );
}
Brad
  • 507
  • 1
  • 4
  • 12
  • have you checked std::string works without pthreads on the platform? – amit kumar Mar 09 '10 at 21:27
  • 1
    And tried, say, 2 threads instead of 100? – indiv Mar 09 '10 at 21:28
  • 1
    yes, too many threads is a likely cause of the seg fault. – amit kumar Mar 09 '10 at 21:30
  • Thanks for responding guys. Yes, I have tried with a couple of threads. It takes longer to show the problem, but still happens. std::string does work (as far as I have seen) on the platform. Could the static mutex cause any issues? I cannot see how any other variables could cause problems as they are being kept within the scope of the static functions. – Brad Mar 09 '10 at 21:37
  • @Brad: are you missing `gcc`'s `-pthread` flag? – Nikolai Fetissov Mar 09 '10 at 21:58
  • @Nikolai: No I was using -lpthread. I have done a little research, and see that it is better to use -pthread. I have tried with this compile option, but unfortunately get the same results. – Brad Mar 10 '10 at 11:08

4 Answers4

5

Maybe you're using a single-threaded version of the standard library, including the new and delete operators?

Those objects are being constructed within the guards of your mutex, but are destructed outside those bounds, so the destructors might be stepping on each other. One quick test would be to put scoping brackets {} around the declaration of killer.

See the gcc documentation for more.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Thanks for the advice Mark. I have tried with the scoping brackets, and the problem goes away. Is this the recommended way of declaring objects inside the Mutex guards, or have I done something fundamentally wrong? When calling "arm-linux-g++ -v" it only yields the version, and does not list --enable-threads at all. Does this mean I am using the single threaded version? As I do not have the option to change the cross-compiler (the provider only supports this one), what is my best course of action? – Brad Mar 10 '10 at 11:24
  • What version does "arm-linux-g++ -v" yield? Passing the `-v` option only prints the version number with my gcc 2.95.2 Arm cross-compiler, but the `-v` option lists `--enable-threads=posix` with my gcc 3.4.5 Arm cross-compiler. – jschmier Mar 17 '10 at 23:20
  • Hi jschmier, Sorry I have been away from the project for some time and back looking at this issue now. Like yourself, passing -v only prints the version number. Unfortunately I am restricted to using the gcc 2.95.2 Arm cross-compiler because this is all the supplier supports with their embedded platform. Have you had the same issue with your cross compiler? How did you work around it? Thanks – Brad Aug 19 '10 at 09:25
0

You don't say what PTHREAD_MUTEX_INITIALIZER is, but are you calling pthread_mutex_init on TestSeg::_logLock? It's possible if you're using an unintialized mutex that stack and/or heap operations from those constructors are interfering with your mutex.

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

Have you tried -Os and -O0 ? whats your arm-linux-g++ --version ?

kert
  • 2,161
  • 21
  • 22
0

When developing and debugging segmentation faults for an embedded Arm Linux platform, I often add code to print a stack backtrace from the SIGSEGV signal handler. Perhaps the implementation I describe here can be of some use to you.

I build with the following gcc/g++ options (among others):

arm-linux-g++ -Wall -pipe -rdynamic -fno-omit-frame-pointer test.cpp -o test
Community
  • 1
  • 1
jschmier
  • 15,458
  • 6
  • 54
  • 72