- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在尝试创建嵌套线程时,helgrind 报告了几种不同类型的数据争用。
==4429== Possible data race during write of size 8 at 0x5673830 by thread #13
==4429== Locks held: none
==4429== at 0x4C379EF: memset (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x5060C85: get_cached_stack (allocatestack.c:250)
==4429== by 0x5060C85: allocate_stack (allocatestack.c:501)
==4429== by 0x5060C85: pthread_create@@GLIBC_2.2.5 (pthread_create.c:537)
==4429== by 0x4C32BF7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x4022D7: read_group (c_esp.c:318)
==4429== by 0x4C32DF6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x50606A9: start_thread (pthread_create.c:333)
==4429== Address 0x5673830 is 16 bytes inside a block of size 560 alloc'd
==4429== at 0x4C2EFB5: calloc (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x40134C4: allocate_dtv (dl-tls.c:322)
==4429== by 0x40134C4: _dl_allocate_tls (dl-tls.c:544)
==4429== by 0x50610D2: allocate_stack (allocatestack.c:588)
==4429== by 0x50610D2: pthread_create@@GLIBC_2.2.5 (pthread_create.c:537)
==4429== by 0x4C32BF7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x4022D7: read_group (c_esp.c:318)
==4429== by 0x4C32DF6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x50606A9: start_thread (pthread_create.c:333)
==4429== Block was alloc'd by thread #3
==4429== Possible data race during write of size 1 at 0x724368F by thread #13
==4429== Locks held: none
==4429== at 0x4C3856C: mempcpy (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x40132F6: _dl_allocate_tls_init (dl-tls.c:520)
==4429== by 0x5060C8D: get_cached_stack (allocatestack.c:253)
==4429== by 0x5060C8D: allocate_stack (allocatestack.c:501)
==4429== by 0x5060C8D: pthread_create@@GLIBC_2.2.5 (pthread_create.c:537)
==4429== by 0x4C32BF7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x4022D7: read_group (c_esp.c:318)
==4429== by 0x4C32DF6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x50606A9: start_thread (pthread_create.c:333)
==4429==
==4429== This conflicts with a previous write of size 1 by thread #4
==4429== Locks held: none
==4429== at 0x5060612: start_thread (pthread_create.c:265)
==4429== Address 0x724368f is in a rw- anonymous segment
==4429== Possible data race during read of size 8 at 0x7243728 by thread #14
==4429== Locks held: none
==4429== at 0x40178C: read_record (c_esp.c:171)
==4429== by 0x4C32DF6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x50606A9: start_thread (pthread_create.c:333)
==4429==
==4429== This conflicts with a previous write of size 8 by thread #13
==4429== Locks held: none
==4429== at 0x5060DB7: pthread_create@@GLIBC_2.2.5 (pthread_create.c:589)
==4429== by 0x4C32BF7: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x4022D7: read_group (c_esp.c:318)
==4429== by 0x4C32DF6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==4429== by 0x50606A9: start_thread (pthread_create.c:333)
==4429== Address 0x7243728 is in a rw- anonymous segment
提到的行是:
318: pthread_create(pth_array + k, &attrs, read_record, args_array +k);
171: void *read_record(void *_args){
所以看起来在创建线程时存在数据竞争?为“不同分支”中的线程分配的堆栈是否可能重叠?还是我搞砸了什么地方?
我已经尝试减少每个线程的堆栈大小,但没有成功。
根据要求,一个最小的可重现示例:
#include <pthread.h>
void *func_b(void *args){
return args;
}
void *func_a(void *args){
pthread_t pth[5];
int i;
for(i = 0; i < 5; i++){
pthread_create(&pth[i], NULL, func_b, NULL);
}
for(i = 0; i < 5; i++){
pthread_join(pth[i], NULL);
}
return args;
}
int main(void){
pthread_t pth[100];
int i;
for(i = 0; i < 100; i++){
pthread_create(&pth[i], NULL, func_a, NULL);
}
for(i = 0; i < 100; i++){
pthread_join(pth[i], NULL);
}
}
helgrind 的完整输出是 here接下来是所有相关代码。此片段从第 171 行到第 477 行。
void *read_record(void *_args){
struct _thread_args *args = (struct _thread_args *)_args;
uint32_t data_size = 0;
args->item->record->type = calloc(5, sizeof *args->item->record->type);
memcpy(args->item->record->type, *args->map, 4);
*args->map += 4;
memcpy(&data_size, *args->map, 4);
*args->map += 4;
memcpy(&args->item->record->flags, *args->map, 4);
*args->map += 4;
memcpy(&args->item->record->id, *args->map, 4);
*args->map += 4;
memcpy(&args->item->record->revision, *args->map, 4);
*args->map += 4;
memcpy(&args->item->record->version, *args->map, 2);
*args->map += 2;
memcpy(&args->item->record->unknown, *args->map, 2);
*args->map += 2;
args->item->record->misc_data = NULL;
args->item->record->children = NULL;
args->item->record->last = NULL;
// args->item->record->next = NULL;
// args->item->record->previous = NULL;
args->item->record->_proxy = NULL;
args->item->record->compression_level = 0x7f; // some invalid number, doesn't matter
if(args->parse_records){
args->item->record->is_parsed = TRUE;
if(args->item->record->flags & 0x00040000){
uLongf uncompressed_size = 0;
memcpy(&uncompressed_size, *args->map, 4);
*args->map += 4;
if(*(*args->map + 1) & (1 << 6)){
if(*(*args->map + 1) & (1 << 7)){
args->item->record->compression_level = Z_BEST_COMPRESSION; // both hight bits are set 11
} else{
args->item->record->compression_level = Z_BEST_SPEED; // 01
}
} else{
if(*(*args->map + 1) & (1 << 7)){
args->item->record->compression_level = Z_DEFAULT_COMPRESSION; // 10
} else{
args->item->record->compression_level = Z_NO_COMPRESSION; // 00
}
}
uint8_t *uncompressed_data = malloc(uncompressed_size * sizeof *uncompressed_data);
uint8_t *start = uncompressed_data;
uncompress(uncompressed_data, &uncompressed_size, *args->map, data_size - 4);
parse_record_data((uint8_t **)&uncompressed_data, uncompressed_size, &args->item->record->children, &args->item->record->last);
*args->map += data_size - 4;
free(start);
} else{
parse_record_data(args->map, data_size, &args->item->record->children, &args->item->record->last);
}
} else{
args->item->record->is_parsed = FALSE;
args->item->record->misc_data = malloc(sizeof *args->item->record->misc_data);
args->item->record->misc_data->data = malloc(data_size * sizeof *args->item->record->misc_data->data);
args->item->record->misc_data->data_size = data_size;
memcpy(args->item->record->misc_data->data, *args->map, data_size);
*args->map += data_size;
}
return NULL;
}
void *read_group(void *_args){
struct _thread_args *args = (struct _thread_args *)_args;
uint32_t data_size = 0;
args->item->group->type = "GRUP";
*args->map += 4;
memcpy(&data_size, *args->map, 4);
*args->map += 4;
memset(args->item->group->label, 0, 5);
memcpy(args->item->group->label, *args->map, 4);
*args->map += 4;
memcpy(&args->item->group->group_type, *args->map, 4);
*args->map += 4;
memcpy(&args->item->group->stamp, *args->map, 2);
*args->map += 2;
memcpy(&args->item->group->unknown1, *args->map, 2);
*args->map += 2;
memcpy(&args->item->group->version, *args->map, 2);
*args->map += 2;
memcpy(&args->item->group->unknown2, *args->map, 2);
*args->map += 2;
args->item->group->children = NULL;
args->item->group->last = NULL;
args->item->group->_proxy = NULL;
uint8_t *data_start = *args->map;
int item_count = 0;
while(*args->map < (data_start + data_size - 24)){
item_count++;
char next_type[5] = {0};
memcpy(next_type, *args->map, 4);
uint32_t next_data_size = 0;
memcpy(&next_data_size, *args->map + 4, 4);
*args->map += next_data_size;
if(strcmp(next_type, "GRUP") != 0){
*args->map += 24;
}
}
*args->map = data_start;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 1000);
struct _group_item *current = NULL;
bool current_is_record = FALSE;
pthread_t *pth_array = malloc(item_count * sizeof *pth_array);
uint8_t **map_array = malloc(item_count * sizeof *map_array);
struct _thread_args *args_array = malloc(item_count * sizeof *args_array);
int k;
for(k = 0; k < item_count; k++){
char next_type[5] = {0};
memcpy(next_type, *args->map, 4);
uint32_t new_data_size = 0;
memcpy(&new_data_size, *args->map + 4, 4);
*(map_array + k) = *args->map;
*args->map += new_data_size;
(*(args_array + k)).map = map_array + k;
(*(args_array + k)).parse_records = args->parse_records;
(*(args_array + k)).item = malloc(sizeof *(*(args_array + k)).item);
if(strcmp(next_type, "GRUP") == 0){
(*(args_array + k)).is_record = FALSE;
(*(args_array + k)).item->group = malloc(sizeof *(*(args_array + k)).item->group);
pthread_create(pth_array + k, &attrs, read_group, args_array + k);
//read_group(args_array + k);
} else{
*args->map += 24;
(*(args_array + k)).is_record = TRUE;
(*(args_array + k)).item->record = malloc(sizeof *(*(args_array + k)).item->record);
pthread_create(pth_array + k, &attrs, read_record, args_array + k);
//read_record(args_array + k);
}
if(args->item->group->children == NULL){
args->item->group->children = current = (*(args_array + k)).item;
args->item->group->children_is_record = current_is_record = (*(args_array + k)).is_record;
if((*(args_array + k)).is_record){
current->record->previous = NULL;
} else{
current->group->previous = NULL;
}
continue;
}
if((*(args_array + k)).is_record){
if(current_is_record){
current->record->next = (*(args_array + k)).item;
current->record->next_is_record = (*(args_array + k)).is_record;
(*(args_array + k)).item->record->previous = current;
(*(args_array + k)).item->record->previous_is_record = current_is_record;
} else{
current->group->next = (*(args_array + k)).item;
current->group->next_is_record = (*(args_array + k)).is_record;
(*(args_array + k)).item->record->previous = current;
(*(args_array + k)).item->record->previous_is_record = current_is_record;
}
} else{
if(current_is_record){
current->record->next = (*(args_array + k)).item;
current->record->next_is_record = (*(args_array + k)).is_record;
(*(args_array + k)).item->group->previous = current;
(*(args_array + k)).item->group->previous_is_record = current_is_record;
} else{
current->group->next = (*(args_array + k)).item;
current->group->next_is_record = (*(args_array + k)).is_record;
(*(args_array + k)).item->group->previous = current;
(*(args_array + k)).item->group->previous_is_record = current_is_record;
}
}
current = (*(args_array + k)).item;
current_is_record = (*(args_array + k)).is_record;
}
args->item->group->last = current;
args->item->group->last_is_record = current_is_record;
if(current != NULL){
if(current_is_record){
current->record->next = NULL;
} else{
current->group->next = NULL;
}
}
int i;
for(i = 0; i < item_count; i++){
pthread_join(*(pth_array + i), NULL);
}
free(pth_array);
free(map_array);
free(args_array);
assert(*args->map == (data_start + data_size - 24));
return NULL;
}
Plugin *plugin_read(const char *filename, const bool parse_records){
Plugin *plugin = malloc(sizeof *plugin);
plugin->children = NULL;
plugin->last = NULL;
plugin->_proxy = NULL;
FILE *fileobject = fopen(filename, "rb");
if(fileobject == NULL){
printf("No file found.\n");
return NULL;
}
fseek(fileobject, 0, SEEK_END);
long int filesize = ftell(fileobject);
rewind(fileobject);
uint8_t *map = malloc(filesize * sizeof *map);
fread(map, filesize, 1, fileobject);
fclose(fileobject);
uint8_t *start = map;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 1000);
pthread_t header_pth;
plugin->header = malloc(sizeof *plugin->header);
struct _group_item header_item;
header_item.record = plugin->header;
uint8_t *header_map = map;
struct _thread_args header_args;
header_args.item = &header_item;
header_args.map = &header_map;
header_args.parse_records = parse_records;
pthread_create(&header_pth, &attrs, read_record, &header_args);
uint32_t header_data_size = 0;
memcpy(&header_data_size, map + 4, 4);
map += header_data_size + 24;
uint8_t *after_header = map;
int group_count = 0;
while(map < (start + filesize)){
group_count++;
uint32_t next_data_size = 0;
memcpy(&next_data_size, map + 4, 4);
map += next_data_size;
}
map = after_header;
pthread_t *pth = malloc(group_count * sizeof *pth);
uint8_t **map_array = malloc(group_count * sizeof *map_array);
struct _thread_args *args = malloc(group_count * sizeof *args);
struct _group_item *current = NULL;
int k;
for(k = 0; k < group_count; k++){
uint32_t new_data_size = 0;
memcpy(&new_data_size, map + 4, 4);
*(map_array + k) = map;
map += new_data_size;
(*(args + k)).item = malloc(sizeof *(*(args + k)).item);
(*(args + k)).item->group = malloc(sizeof *(*(args + k)).item->group);
(*(args + k)).map = map_array + k;
(*(args + k)).parse_records = parse_records;
pthread_create(pth + k, &attrs, read_group, args + k);
if(plugin->children == NULL){
plugin->children = (*(args + k)).item;
current = (*(args + k)).item;
current->group->previous = NULL;
continue;
}
current->group->next = (*(args + k)).item;
current->group->next_is_record = FALSE;
(*(args + k)).item->group->previous = current;
(*(args + k)).item->group->previous_is_record = FALSE;
current = (*(args + k)).item;
}
plugin->last = current;
plugin->last->group->next = NULL;
pthread_join(header_pth, NULL);
int i;
for(i = 0; i < group_count; i++){
pthread_join(*(pth + i), NULL);
}
assert(map == (start + filesize));
free(start);
free(pth);
free(args);
free(map_array);
return plugin;
}
谢谢!
最佳答案
尝试 --sim-hints=no-nptl-pthread-stackcache。
参见 http://www.valgrind.org/docs/manual/manual-core.html#manual-core.rareopts获取更多信息。
关于c - 嵌套线程创建期间的数据竞争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40113375/
前言: 有时候,一个数据库有多个帐号,包括数据库管理员,开发人员,运维支撑人员等,可能有很多帐号都有比较大的权限,例如DDL操作权限(创建,修改,删除存储过程,创建,修改,删除表等),账户多了,管理
所以我用 Create React App 创建并设置了一个大型 React 应用程序。最近我们开始使用 Storybook 来处理和创建组件。它很棒。但是,当我们尝试运行或构建应用程序时,我们不断遇
遵循我正在创建的控件的代码片段。这个控件用在不同的地方,变量也不同。 我正在尝试编写指令来清理代码,但在 {{}} 附近插入值时出现解析错误。 刚接触 Angular ,无法确定我错过了什么。请帮忙。
我正在尝试创建一个 image/jpeg jax-rs 提供程序类,它为我的基于 post rest 的 Web 服务创建一个图像。我无法制定请求来测试以下内容,最简单的测试方法是什么? @POST
我一直在 Windows 10 的模拟器中练习 c。后来我改用dev C++ IDE。当我在 C 中使用 FILE 时。创建的文件的名称为 test.txt ,而我给出了其他名称。请帮助解决它。 下面
当我们创建自定义 View 时,我们将 View 文件的所有者设置为自定义类,并使用 initWithFrame 或 initWithCode 对其进行实例化。 当我们创建 customUITable
我正在尝试为函数 * Producer 创建一个线程,但用于创建线程的行显示错误。我为这句话加了星标,但我无法弄清楚它出了什么问题...... #include #include #include
今天在做项目时,遇到了需要创建JavaScript对象的情况。所以Bing了一篇老外写的关于3种创建JavaScript对象的文章,看后跟着打了一遍代码。感觉方法挺好的,在这里与大家分享一下。 &
我正在阅读将查询字符串传递给 Amazon 的 S3 以进行身份验证的文档,但似乎无法理解 StringToSign 的创建和使用方式。我正在寻找一个具体示例来说明 (1) 如何构造 String
前言:我对 C# 中任务的底层实现不太了解,只了解它们的用法。为我在下面屠宰的任何东西道歉: 对于“我怎样才能开始一项任务但不等待它?”这个问题,我找不到一个好的答案。在 C# 中。更具体地说,即使任
我有一个由一些复杂的表达式生成的 ILookup。假设这是按姓氏查找人。 (在我们简单的世界模型中,姓氏在家庭中是唯一的) ILookup families; 现在我有两个对如何构建感兴趣的查询。 首
我试图创建一个 MSI,其中包含 和 exe。在 WIX 中使用了捆绑选项。这样做时出错。有人可以帮我解决这个问题。下面是代码: 错误 error LGH
在 Yii 中,Create 和 Update 通常使用相同的形式。因此,如果我在创建期间有电子邮件、密码、...other_fields...等字段,但我不想在更新期间专门显示电子邮件和密码字段,但
上周我一直在努力创建一个给定一行和一列的 QModelIndex。 或者,我会满足于在已经存在的 QModelIndex 中更改 row() 的值。 任何帮助,将不胜感激。 编辑: QModelInd
出于某种原因,这不起作用: const char * str_reset_command = "\r\nReset"; const char * str_config_command = "\r\nC
现在,我有以下由 original.df %.% group_by(Category) %.% tally() %.% arrange(desc(n)) 创建的 data.frame。 DF 5),
在今天之前,我使用/etc/vim/vimrc来配置我的vim设置。今天,我想到了创建.vimrc文件。所以,我用 touch .vimrc cat /etc/vim/vimrc > .vimrc 所
我可以创建一个 MKAnnotation,还是只读的?我有坐标,但我发现使用 setCooperative 手动创建 MKAnnotation 并不容易。 想法? 最佳答案 MKAnnotation
在以下代码中,第一个日志语句按预期显示小数,但第二个日志语句记录 NULL。我做错了什么? NSDictionary *entry = [[NSDictionary alloc] initWithOb
我正在使用与此类似的代码动态添加到数组; $arrayF[$f+1][$y][$x+1] = $value+1; 但是我在错误报告中收到了这个: undefined offset :1 问题:尝试创
我是一名优秀的程序员,十分优秀!