【问题标题】:"new" operator in multiple threads causes Segmentation Fault多线程中的“new”运算符导致分段错误
【发布时间】:2010-08-26 14:46:11
【问题描述】:

这与我一直在讨论 herehere 的问题有关,但由于我的调查使我远离了 STL 作为潜在问题,而将“新”作为我的克星,我认为最好开始一个新线程。

重申一下,我使用的是嵌入式平台供应商提供的 arm-linux 交叉编译器(版本 2.95.2)。

当我在我的 Linux PC 上运行以下应用程序时,它当然永远不会失败。但是,在嵌入式设备上运行它时,我每次都会遇到分段错误。使用“malloc”永远不会失败。使用互斥锁同步“新”分配将停止该问题,但这在我的主应用程序中不实用。

谁能说明为什么会发生这种情况,或者有什么想法可以解决这个问题?

谢谢。

#include <stdio.h>
#include <pthread.h>


pthread_mutex_t _logLock = PTHREAD_MUTEX_INITIALIZER;

static void* Thread(void *arg)
{
    int i = 0;
    while (i++ < 500)
    {
        // pthread_mutex_lock(&_logLock);
        char* myDyn = (char*) new char[1023];

        //        char* buffer = (char*) malloc(1023);
        //        if (buffer == NULL)
        //            printf("Out of mem\n");
        //        free(buffer);


        delete[] myDyn;

        //pthread_mutex_unlock(&_logLock);


    }
    pthread_exit(NULL);
}

int main(int argc, char** argv)
{
    int threads = 50;
    pthread_t _rx_thread[threads];
    for (int i = 0; i < threads; i++)
    {
        printf("Start Thread: %i\n", i);
        pthread_create(&_rx_thread[i], NULL, Thread, NULL);
    }

    for (int i = 0; i < threads; i++)
    {
        pthread_join(_rx_thread[i], NULL);
        printf("End Thread: %i\n", i);
    }
}

【问题讨论】:

  • 你应该尝试用 try/catch 包装 new/delete 并在 std::bad_alloc 上进行例外处理,看看你从那里得到了什么。
  • 您是否使用-pthread 标志进行编译和链接?

标签: c++ linux arm segmentation-fault new-operator


【解决方案1】:

如果您设备上的堆不是线程安全的,那么您需要锁定。您可以编写自己的 new 和 delete 函数,在 new 或 delete 期间锁定 - 您不需要在分配的内存的整个生命周期内保持锁定。

检查是否有编译器开关使分配器线程安全。

【讨论】:

  • Lou,我很感激我可以重载 new / delete 运算符,并且正在研究这个选项。但是我担心我调用的库(例如 STL)不会使用这些。你遇到过什么样的编译器开关?乍一看我找不到合适的东西。
  • 对于 STL,覆盖分配器。 codeguru.com/Cpp/Cpp/cpp_mfc/stl/article.php/c4079
  • 我不知道您使用的是什么编译器——但有些编译器具有使其使用运行时的多线程安全版本的开关(Visual Studio 有这个)。您可能想与嵌入式设备的供应商交谈。
【解决方案2】:

正如其他人所说,工具集的默认内存分配行为可能不是线程安全的。我刚刚检查了我最常使用的 2 个 ARM 交叉开发工具集,其中一个确实是这种情况。

大多数工具集都提供了使库线程安全的方法,方法是重新实现函数或链接到库的不同(线程安全)版本。如果没有您提供的更多信息,很难说出您的特定工具集在做什么。

不想这么说,但最好的信息可能在您的工具集文档中。

【讨论】:

  • Dan,我对交叉编译比较陌生,并且正在使用我正在使用的设备供应商提供的工具集。我将如何检查?
【解决方案3】:

是的,new 可能不是线程安全的。您需要围绕内存分配的同步机制,以及单独围绕删除的同步机制。查看Boost.thread library,它提供了可以帮助您的互斥体类型。

【讨论】:

    【解决方案4】:

    如何使用 malloc(你说它在嵌入式平台上永远不会失败)来获取所需的内存,然后使用placement new (void* operator new[] (std::size_t size, void* ptr) throw()) 假设它是可用的,用于建设。看 new[] operator

    还有see stackoverflow article

    MSDN

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 2020-07-14
      • 2011-01-29
      • 2013-08-21
      相关资源
      最近更新 更多