双重释放或损坏(!prev)pthread [英] double free or corruption (!prev) pthread
问题描述
在实现多线程程序时遇到问题.
该程序对于单线程(当我将THREADS设置为1时)似乎工作正常,但是对于NTHREADS> 1,我得到以下错误:
Segmentation fault (core dumped)
I'm having issues while implementing a multithread program.
The program seems to work fine for a single thread (when I set THREADS to 1) but for NTHREADS > 1, I'm getting the following error:
Segmentation fault (core dumped)
或
double free or corruption (!prev)
或
free(): invalid size: 0xb6b00a10 ***
0Aborted (core dumped)
free(): invalid size: 0xb6b00a10 ***
0Aborted (core dumped)
如您所见,错误变化很大,我感到困惑.
as you can see the error varies a lot and I'm getting confused.
我正在执行的程序如下:
The program I'm executing is the following:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#define NTHREADS 5
typedef struct data_t
{
int num;
FILE *fp;
pthread_mutex_t mutex;
int thread_id;
}data_t;
void writefp(int num1, FILE *fp){
if(fp!=NULL){
int i;
int nume = 1;
int long_var=log10(nume);
for(i=long_var;i>=0;i--){
nume=(num1 / (int) round(pow(10, i)) % 10);
char d=nume+'0';
fwrite(&d, 1, 1, fp);
printf("%c", d);
}
}
fclose(fp);
}
void *thread_writefp(void* args)
{
data_t *data = (data_t *)args;
printf(" Thread id %d\n", data->thread_id);
pthread_mutex_lock(&(data->mutex));
writefp(data->num, data->fp);
pthread_mutex_unlock(&(data->mutex));
pthread_exit(NULL);
}
int randomf(){
int num,i;
for(i = 0; i<2; i++) {
num = rand()%100000+1;
}
return num;
}
int prime(int num1){
int is_prime=1;
int i = 2;
printf("Number: ");
while( i<=num1/2 && is_prime==1 ) {
printf("%i ", i);
if(i%30==0){
printf("\n");
}
if( num1 % i == 0 ) {
is_prime = 0;
}
i++;
}
printf("\n");
if(is_prime){
printf("%i is number prime\n", num1);
}else{
printf("NO is prime %i\n",num1);
}
return 0;
}
int main(void){
int i;
//int num1=randomf();
srand(time(NULL));
FILE *fp = fopen("fich.txt", "w+b");
data_t data;
pthread_t consumers_thread[NTHREADS];
data.mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
data.fp = fp;
//writefp( num1, fp);
for(i = 0; i < NTHREADS; i++)
{
data.num = randomf();
data.thread_id = i;
printf("Number prime is %i\n", prime(data.num));
if(pthread_create(&consumers_thread[i], NULL,
thread_writefp, (void*) &data) != 0)
{
fprintf(stderr, "%s\n", "Error creating thread!");
return EXIT_FAILURE;
}
}
// wait for all consumers thread to finish
for(i = 0; i < NTHREADS; ++i)
{
pthread_join(consumers_thread[i], NULL);
}
return EXIT_SUCCESS;
}
我将程序编译如下:
$gcc -pthread -Wall -o consummer consummer.c -lm
这里是示例树错误,当我连续使用gdb
树运行它而没有更改代码时得到的错误:
Here are for exemple tree error I got when I ran it with gdb
tree successive time without changing anything to the code:
Thread 2 "consummer" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7cc1b40 (LWP 18122)]
tcache_thread_freeres () at malloc.c:3003
3003 malloc.c: No such file or directory.
(gdb) bt
#0 tcache_thread_freeres () at malloc.c:3003
#1 0xb7e258c2 in __libc_thread_freeres () at thread-freeres.c:29
#2 0xb7ea03ad in start_thread (arg=0xb7cc1b40) at pthread_create.c:478
#3 0xb7dbb0a6 in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:108
(gdb)
2
Thread 3 "consummer" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb72ffb40 (LWP 18131)]
0xb7d2af2b in __GI__IO_fwrite (buf=0xb72ff30f, size=1, count=1, fp=0x404160) at iofwrite.c:37
37 iofwrite.c: No such file or directory.
(gdb) run
3
Thread 3 "consummer" received signal SIGABRT, Aborted.
[Switching to Thread 0xb74c0b40 (LWP 18143)]
0xb7fd7cf9 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fd7cf9 in __kernel_vsyscall ()
#1 0xb7cf17e2 in __libc_signal_restore_set (set=0xb74bfe9c) at ../sysdeps/unix/sysv/linux/nptl-signals.h:80
#2 __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:48
#3 0xb7cf2f51 in __GI_abort () at abort.c:90
#4 0xb7d340cc in __libc_message (action=(do_abort | do_backtrace), fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:181
#5 0xb7d3af5d in malloc_printerr (action=<optimized out>, str=0xb7e418d8 "double free or corruption (!prev)", ptr=<optimized out>,
ar_ptr=0xb7e967a0 <main_arena>) at malloc.c:5425
#6 0xb7d3bb3b in _int_free (av=0xb7e967a0 <main_arena>, p=<optimized out>, have_lock=have_lock@entry=0) at malloc.c:4174
#7 0xb7d3fcb0 in __GI___libc_free (mem=0x404160) at malloc.c:3144
#8 0xb7e2587d in tcache_thread_freeres () at malloc.c:3004
#9 0xb7e258c2 in __libc_thread_freeres () at thread-freeres.c:29
#10 0xb7ea03ad in start_thread (arg=0xb74c0b40) at pthread_create.c:478
#11 0xb7dbb0a6 in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:108
(gdb)
我想/感谢您的帮助,请知道我做错了什么.提前致谢.
I'd like/apreciate your help to know what I did wrong please. Thanks in advance.
推荐答案
每此答案(但请参阅编辑2 ),则多个线程无法安全地访问相同的FILE *fp
.正如@IlyaBursov所指出的,您在所有线程中只有一个data_t data
共享—因此,只有一个FILE *
data.fp
.
Per this answer (but see Edit 2), multiple threads cannot safely access the same FILE *fp
. As @IlyaBursov pointed out, you only have one data_t data
shared across all threads — and, therefore, only one FILE *
data.fp
.
感谢您的评论,指出您已将FILE *
共享.
Thanks for your comment noting that you moved the fopen
into the thread function. That way each thread independently opens and closes the file, so there is no FILE *
sharing between threads.
这似乎是与实现有关的—我无法使用gcc 6.4.0在Cygwin x64上重现该问题.我怀疑互斥锁的效果也可能因实现方式而异.它也可能取决于编译器选项—.参见此示例.
This seems to be implementation-dependent — I was not able to reproduce the issue on Cygwin x64 with gcc 6.4.0. I suspect the effect of the mutex may also vary by implementation. It may also be dependent on compiler options — see this example.
编辑正如@MichaelDorgan指出的那样,在其他线程正在使用的FILE *
上调用fclose
也是一个坏主意.
Edit As @MichaelDorgan pointed out, calling fclose
on a FILE *
that other threads are using is also a bad idea.
编辑2 正如@JohnBollinger指出的那样,符合fwrite
只会在访问已关闭文件时返回错误,而不是崩溃. 请参阅下面的其他评论.
Edit 2 As @JohnBollinger points out, individual stream operations are thread-safe these days. That would suggest that the fclose
before another thread tried to access the file might be the problem. However, I wonder if perhaps the OP's stdio implementation is non-conformant in some way. I would think a compliant fwrite
would simply return error on an access to a closed file, rather than crashing. See further comments below.
这篇关于双重释放或损坏(!prev)pthread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!