2010-04-28 60 views
2

当我malloc pthread_t保存一个新创建的线程ID并将它释放到另一个线程时发生故障地址。代码如下:线程的malloc/free pthread_t时的故障地址

typedef struct _TaskInfo { 
    // int dummy_int; 
    pthread_t tid; 
} TaskInfo; 

void* dummy_task(void* pArg) { 
    free(pArg); 
    return NULL; 
} 

void create_task() { 
    TaskInfo *pInfo; 
    pthread_attr_t attr; 

    // set detached state stuff ... 

    pInfo = (TaskInfo*) malloc(sizeof(TaskInfo)); 
    pthread_create(&pInfo->tid, &attr, dummy_task, pInfo); 

    // destroy pthread attribute stuff ... 
} 

int main() { 
    int i; 
    while(i < 10000) { 
     create_task(); 
     ++i; 
    } 
    return 0; 
} 

当我取消注释TaskInfo的成员dummy_int时,它有时会成功运行,但有时会失败。 我的平台是VMWare + Ubuntu 9.10 + ndk r3

谢谢!

回答

1

pthread_create()存储在位置所创建的线程的线程ID(TID)指向的第一个参数,但是它确实该线程被创建后(http://opengroup.org/onlinepubs/007908799/xsh/pthread_create.html):

成功完成后,在pthread_create ()将在该位置由螺纹

引用因为线程已经创建所创建的线程的ID,很可能有机会pthread_create()之前运行和删除的内存块都有机会来存储在它的TID。

如果在结构中没有dummy_int成员,您可能会以早崩溃的方式破坏堆。随着dummy_int成员包括在内,你碰巧会贬低一些不那么敏感的东西(所以崩溃的频率不那么频繁)。在这两种情况下,你都在抛弃未分配的内存(或者可能未分配 - 你有竞争条件)。

+0

非常感谢!但我仍然想知道为什么Linux上的相同代码工作正常。因为我从Robert Love的“Linux内核开发”中读到内核首先运行子进程,Linux上进程和线程的执行是相同的。 Linux上的线程调度与android不同吗? – scleung 2010-04-28 07:22:39

+0

我不能说 - 但无论哪种情况,由于您正在处理竞争条件,您正在处理的代码在某些时候会失败。这可能是因为Android上的故障更加“确定”,因为您可能使用单个处理器设备,而在Linux上,您可能正在运行多处理器设备,因此原始线程有机会在TID之前保存TID 'free()'出现在新创建的线程中。或者Linux可能在调度程序中有足够的差异来让你摆脱困境。但它仍然是错误的 - 在某些情况下你只是没有注意到它。 – 2010-04-28 07:33:59