Pthreaded程序导致Linux机器上的分段错误。适用于Cygwin64

时间:2014-03-29 16:41:02

标签: c++ segmentation-fault cygwin malloc heap

基础知识

创建了一个程序来测试C ++中的多线程和单线程Heap实现。该程序基于全局数据结构构建和处理它的堆,该全局数据结构由2 ^ 20个无符号整数的STL向量2 ^ 8个STL向量组成,所述无符号整数由稍微随机数组成。

主数据结构正确初始化,我的程序当前分为两个测试阶段,其中一个调用函数以顺序方式执行算法,将结果转储到一个全局数组中,该数组与sub相同 - 上述数据结构中的向量(2 ^ 8),其中该数组中的每个元素指定向量主向量中相同索引处的子向量的结果。

第二阶段完全相同,但并行地,使用多个pThreads从主矢量并行处理子矢量组。第二阶段将结果转储到第一个单独的数组中,其中两个结果数组用于比较和校正检查。

因此,主要的数据结构,向量的向量只能从程序的两个阶段读取。每个阶段都写入不同的全局数组,但是在指定该数组中不同元素的索引处。

该算法从每个子向量中构建一个堆,并以顺序方式对该子向量中的元素执行一系列更新 - 密钥操作,直到它耗尽了子向量中的所有元素。第一阶段通过以顺序方式处理每个子矢量来执行此操作,第二阶段通过并行处理子矢量组来完成此操作。

问题是,当我在Cygwin64下的Windows机器上执行程序时,程序正确执行。没有错误,结果正确,一切正常。即使使用较小的数据集进行测试也表明算法正在正确执行。

问题

以下是程序的Cygwin64执行。

D-Value: 64
List Set Size: 256
Sub-List Size: 1048576
K-Value: 104857
D-Heap Offset: 63
Ad-Heap Offset: 63


Number Of POSIX Threads: 4

Initializing the list of sub-lists to be be processed.

Please wait while building answer array by serially processing the sub-lists.

Finished testing for the kth element in each sub list using CPU serially.

CPU Wall-Clock Time: 45.2943s
CPU Processor Time: 45.286s

Begin testing for the kth element in each sub list using CPU with POSIX threads.

Finished testing for the kth element in each sub list using CPU and parallel POSIX      threads.

POSIX Threaded CPU Wall-Clock Time: 12.7866s
POSIX Threaded CPU Processor Time: 50.202s

The results are correct!

一切正常,即使我通过输入减少POSIX线程的数量,或者改变数据结构的大小,它也能正常工作。如果我足够减小数据结构的大小以便检查结果(例如,256个元素的256个子向量),我可以看到算法返回的结果是正确的。所以算法应该正确执行。

如果我在任何Linux机器上执行相同的程序:

D-Value: 64
List Set Size: 256
Sub-List Size: 1048576
K-Value: 104857
D-Heap Offset: 63
Ad-Heap Offset: 63


Number Of POSIX Threads: 4

Initializing the list of sub-lists to be be processed.

Please wait while building answer array by serially processing the sub-lists.
Segmentation Fault (core dumped)

它甚至没有通过这一点,我只是顺序执行算法。但是,如果我将子向量的数量减少到1。

D-Value: 64
List Set Size: 1
Sub-List Size: 1048576
K-Value: 104857
D-Heap Offset: 63
Ad-Heap Offset: 63


Number Of POSIX Threads: 1

Initializing the list of sub-lists to be be processed.

Please wait while building answer array by serially processing the sub-lists.

Finished testing for the kth element in each sub list using CPU serially.

CPU Wall-Clock Time: 0.23356s
CPU Processor Time: 0.19s

Begin testing for the kth element in each sub list using CPU with POSIX threads.

Finished testing for the kth element in each sub list using CPU and parallel POSIX      threads.

POSIX Threaded CPU Wall-Clock Time: 0.237998s
POSIX Threaded CPU Processor Time: 0.19s

The results are correct!

如果将子矢量的数量增加到大于1的任何大小,则返回分段错误。所以我用gdb试着看看我是否能确定出现分段错误的位置。

Please wait while building answer array by serially processing the sub-lists.

Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x7ffff7398740 <main_arena>, bytes=<optimized out>)
at malloc.c:3445
3445    malloc.c: No such file or directory.
(gdb) bt
#0  _int_malloc (av=0x7ffff7398740 <main_arena>, bytes=<optimized out>)
    at malloc.c:3445
#1  0x00007ffff705a4d0 in __GI___libc_malloc (bytes=419680) at malloc.c:2859
#2  0x0000000000401eaf in Heap_Build (main_list_index=1) at ad_heap.cpp:312
#3  0x00000000004018bc in main (argc=7, argv=0x7fffffffdf48) at ad_heap.cpp:203

因此程序在函数Heap_Build中的malloc调用失败。这个函数基本上通过构建堆来执行算法,从子向量执行堆上的更新 - 密钥操作序列。程序的第一阶段以顺序方式调用此函数,第二阶段允许每个pThread调用函数来处理它们的子向量组。

unsigned int Heap_Build(unsigned int main_list_index)
{
    unsigned int num_of_nodes = 0;
    unsigned int *heap = (unsigned int*) malloc((k+usage_offset) * sizeof(unsigned int));
    unsigned int sublist_value;

    for(int i = 0; i < k; i++)
    {

        sublist_value = main_list.at(main_list_index).at(i);

        num_of_nodes = Heap_Insert_Node(heap, sublist_value, num_of_nodes); 
    }


    for(int i = k; i < sub_list_size; i++)
    {
        sublist_value = main_list.at(main_list_index).at(i);


        if(sublist_value < heap[usage_offset])
        {
            Heap_Update_Key_CPU(heap, 0, sublist_value, num_of_nodes);
        }
    }
    return heap[usage_offset];
    free(heap);
}

在这段代码中似乎没有任何可疑之处,k是堆的大小,k + usage_offset是表示堆的数组的大小。返回值只是堆的根。用作堆的无符号整数的malloc'd数组结构在使用后是免费的。

我真的不确定为什么上面的代码会在Cygwin64上正确执行,给出正确的结果和所有内容,而不是在任何Linux机器上。

1 个答案:

答案 0 :(得分:1)

malloc中的崩溃是内存损坏的标志 使用valgrind和co(mcheck,电围栏,tcmalloc等),通常会有所帮助。

如果你想让人们为你的运动修改你的程序,那么在某处(github,例如)发布完整的源代码(或者更好的,一个仍然显示问题的最小测试用例)。