【问题标题】:Seg Fault when using std::string on an embedded Linux platform在嵌入式 Linux 平台上使用 std::string 时出现段错误
【发布时间】:2010-03-09 21:22:16
【问题描述】:

我在嵌入式 Arm Linux 平台上运行的应用程序出现问题已经工作了几天。不幸的是,该平台使我无法使用任何常用的有用工具来查找确切的问题。在运行 Linux 的 PC 上运行相同的代码时,我没有收到此类错误。

在下面的示例中,我可以通过取消注释字符串、列表或向量行来可靠地重现问题。让他们评论会导致应用程序运行完成。我预计某些东西正在破坏堆,但我看不到什么?该程序将运行几秒钟,然后给出分段错误。

代码使用arm-linux交叉编译器编译:

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

非常感谢任何想法。

#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 );
}

【问题讨论】:

  • 你检查过 std::string 在平台上没有 pthreads 的情况下工作吗?
  • 并尝试了 2 个线程而不是 100 个线程?
  • 是的,线程过多可能是导致 seg 错误的原因。
  • 感谢大家的回复。是的,我尝试了几个线程。显示问题需要更长的时间,但仍然会发生。 std::string 在平台上确实有效(据我所知)。静态互斥锁会导致任何问题吗?我看不出任何其他变量如何导致问题,因为它们被保留在静态函数的范围内。
  • @Brad:你错过了gcc-pthread 标志吗?

标签: c++ linux string segmentation-fault arm


【解决方案1】:

也许您正在使用标准库的单线程版本,包括 newdelete 运算符?

那些对象是在你的互斥体的守卫内构造的,但在这些边界之外被破坏,所以析构函数可能会互相踩踏。一种快速测试是将范围括号 {} 放在 killer 的声明周围。

请参阅the gcc documentation 了解更多信息。

【讨论】:

  • 感谢马克的建议。我已经尝试过使用范围括号,问题就消失了。这是在 Mutex 守卫内声明对象的推荐方式,还是我做错了什么?当调用“arm-linux-g++ -v”时,它只产生版本,根本不列出 --enable-threads。这是否意味着我使用的是单线程版本?由于我没有更改交叉编译器的选项(提供商只支持这个),我最好的做法是什么?
  • "arm-linux-g++ -v" 产生什么版本?传递 -v 选项仅使用我的 gcc 2.95.2 Arm 交叉编译器打印版本号,但 -v 选项使用我的 gcc 3.4.5 Arm 交叉编译器列出 --enable-threads=posix
  • 嗨 jschmier,对不起,我已经离开这个项目一段时间了,现在回头看看这个问题。像你自己一样,传递 -v 只打印版本号。不幸的是,我仅限于使用 gcc 2.95.2 Arm 交叉编译器,因为这是供应商对其嵌入式平台的所有支持。你的交叉编译器有同样的问题吗?你是如何解决它的?谢谢
【解决方案2】:

你没有说 PTHREAD_MUTEX_INITIALIZER 是什么,但你是在 TestSeg::_logLock 上调用 pthread_mutex_init 吗?如果您使用的是未初始化的互斥锁,则这些构造函数的堆栈和/或堆操作会干扰您的互斥锁。

【讨论】:

  • PTHREAD_MUTEX_INITIALIZER 是静态初始化 POSIX 互斥体而不调用 pthread_mutex_init(3) 的标准方法。
【解决方案3】:

你试过 -Os 和 -O0 吗?你的 arm-linux-g++ --version 是什么?

【讨论】:

    【解决方案4】:

    在为嵌入式 Arm Linux 平台开发和调试分段错误时,我经常添加代码以从 SIGSEGV 信号处理程序打印堆栈 backtrace。也许我描述的 here 的实现对你有一些用处。

    我使用以下 gcc/g++ 选项(以及其他选项)进行构建:

    arm-linux-g++ -Wall -pipe -rdynamic -fno-omit-frame-pointer test.cpp -o test
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-21
      • 2010-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多