2013-07-14 47 views
15

Bất cứ khi nào tôi có thể tạo một pthread, valgrind kết quả đầu ra rò rỉ bộ nhớ,tại sao pthread gây ra một bộ nhớ bị rò rỉ

Ví dụ đoạn code dưới đây:

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

void *timer1_function (void *eit){ 
    (void) eit; 
    printf("hello world\n"); 
    pthread_exit(NULL); 
} 

int main(void){ 
    pthread_t timer1; 
    pthread_create(&timer1, NULL, timer1_function, NULL); ///////line13 
    int i=0; 
    for(i=0;i<2;i++){usleep(1);} 
    return 0; 
} 

đầu ra valgrind

==1395== HEAP SUMMARY: 
==1395==  in use at exit: 136 bytes in 1 blocks 
==1395== total heap usage: 6 allocs, 5 frees, 1,134 bytes allocated 
==1395== 
==1395== 136 bytes in 1 blocks are possibly lost in loss record 1 of 1 
==1395== at 0x402A629: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==1395== by 0x4011304: allocate_dtv (dl-tls.c:297) 
==1395== by 0x4011AAB: _dl_allocate_tls (dl-tls.c:461) 
==1395== by 0x4052470: [email protected]@GLIBC_2.1 (allocatestack.c:571) 
==1395== by 0x8048566: main (test.c:13) 
==1395== 
==1395== LEAK SUMMARY: 
==1395== definitely lost: 0 bytes in 0 blocks 
==1395== indirectly lost: 0 bytes in 0 blocks 
==1395==  possibly lost: 136 bytes in 1 blocks 
==1395== still reachable: 0 bytes in 0 blocks 
==1395==   suppressed: 0 bytes in 0 blocks 

tại sao nguyên nhân pthread_create một vấn đề mặc dù tôi đã sử dụng trang người đàn ông làm tài liệu tham khảo, và làm thế nào tôi có thể sửa nó?

+0

có thể trùng lặp với [lỗi rò rỉ bộ nhớ valgrind khi sử dụng pthread \ _create] (http: // stackoverflow.com/questions/5610677/valgrind-memory-leak-errors-khi-sử dụng-pthread-create) – nos

Trả lời

22

Một chủ đề là một nguồn tài nguyên được phân bổ và bạn đã không giải phóng nó trước khi thoát. Bạn nên gọi pthread_join; điều này cũng sẽ loại bỏ sự cần thiết cho hackish của bạn và vòng lặp ngủ không chính xác. Có thể là ngay cả khi bạn sửa lỗi này, valgrind sẽ vẫn thấy "rò rỉ", vì một số triển khai các chủ đề POSIX (tôi đoán bạn đang sử dụng glibc/NPTL) và sử dụng lại tài nguyên luồng thay vì giải phóng chúng đầy đủ. Tôi không chắc chắn nếu valgrind làm việc xung quanh điều này hay không.

+1

+1. Tôi nghĩ đoạn thứ hai của bạn giải thích lý do tại sao tôi đã nhìn thấy cách tiếp cận đàn áp trong câu trả lời của tôi thường xuyên được sử dụng. – simonc

+0

Thay thế cho pthread_join: sử dụng pthread_detach nhưng vẫn bị rò rỉ bộ nhớ. – Aubin

4

Tôi nghĩ rằng valgrind phân tích trạng thái chương trình của bạn tại thời điểm thoát, có khả năng trước khi kết thúc quá trình thực thi: hai micro giây có thể không đủ để viết "Hello, world!\n" cho bảng điều khiển. Thêm một cuộc gọi đến pthread_join nên sửa chữa rò rỉ này:

pthread_join(timer1, NULL); 
+3

Bạn chỉ có thể truyền một con trỏ null cho đối số thứ hai thay vì một con trỏ tới một biến giả. –

+0

@R .. Vâng, tôi đoán bạn đã đúng ... OP chuyển 'NULL' thành' pthread_exit', vì vậy 'pthread_join' cũng có thể bỏ qua kết quả một cách rõ ràng. Cảm ơn! – dasblinkenlight

0

rò rỉ bộ nhớ là kết quả của thực tế là nếu luồng được chạy mà không hủy, thì bộ nhớ được cấp phát động tương ứng sẽ không được giải phóng. Sử dụng pthread_cancel() cùng với pthread_cleanup_push (CleanupHandler, NULL) và pthread_cleanup_pop (0) để xóa sạch chuỗi sau khi hủy.

1

Tôi đã thấy kết quả tương tự khi tôi không gọi pthread_join.

Khi tôi gọi pthread_join, Valgrind sẽ cho biết không có lỗi bộ nhớ hoặc rò rỉ. Tôi đã có một kết quả rõ ràng bằng cách sử dụng pthread_kill để xem nếu thread vẫn còn tồn tại, sau đó gọi tham gia để làm sạch và phát hành tài nguyên.

int 
stop_worker(worker_t *self) 
{ 
    if (self) { 
     // signal the thread to quit 
      // (here using a variable and semaphore) 
     self->thread_quit=TRUE; 
     sem_post(&self->sem); 

     // wait for it to stop 
     // (could use counter, etc. to limit wait) 
     int test=0; 
     while (pthread_kill(self->thread,0) == 0) { 
      MDEBUG(MD_XF_LOGGER,"waiting for thread to exit...\n",test); 
      delay_msec(50); 
     } 

     // even though thread is finished, need to call join 
     // otherwise, it will not release its memory (and valgrind indicates a leak) 
     test=pthread_join(self->thread,NULL); 
     return 0;   
    } 
    return -1; 
} 
0

Cấu trúc DTV (Dynamic Thread Vector) được phân bổ trong lưu trữ cục bộ của chủ đề con (tls).

Sử dụng pthread_join() trong chủ đề chính (ví dụ: chủ đề sinh ra đứa trẻ) sẽ đảm bảo khắc phục sự cố rò rỉ. Đối với trường hợp sử dụng mà không cần gọi pthread_join(), gọi số pthread_detach với pthread_t con đảm bảo bộ nhớ được giải phóng.

Từ người đàn ông cho pthread_detach:

Chức năng pthread_detach() đánh dấu các chủ đề được xác định bởi thread như tách ra. Khi một luồng tách rời kết thúc, tài nguyên của nó là sẽ tự động được trả về hệ thống mà không cần một luồng khác để tham gia với chuỗi đã kết thúc.

Các vấn đề liên quan