ПроблемаУтечка памяти для конкретного потока происходит, когда вы не освобождаете динамически выделенную память для конкретного потока до конца потока.
Чтобы создать специфичное для потока хранилище, вы обычно делаете следующие шаги:
Вы создаете ключ для специфичного для потока хранилища.
Вы создаете потоки.
В каждом потоке вы динамически выделяете устройство хранения данных, а затем связываете ключ с этим устройством хранения.
После ассоциации можно считать сохраненные данные позже с помощью ключа.
Перед завершением потока вы освобождаете определенную для потока память с помощью ключа.
Шашка помечает пути выполнения в потоке, где отсутствует последний шаг.
Шашка работает с этими семействами функций:
РискДанные, хранящиеся в памяти, доступны другим процессам даже после окончания потоков (утечка памяти). Помимо уязвимостей безопасности, утечки памяти могут уменьшить объем доступной памяти и снизить эффективность.
ЗафиксироватьОсвободите динамически выделенную память перед концом потока.
Вы можете явно освободить динамически выделенную память с такими функциями, как free.
Кроме того, когда вы создаете ключ, можно связать функцию деструктора с клавишей. Функция деструктора вызывается со значением ключа в качестве аргумента в конце потока. В теле функции деструктора можно освободить любую память, связанную с клавишей. Если вы используете этот метод, Bug Finder все еще помечает дефект. Игнорируйте этот дефект с соответствующими комментариями. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.
Пример - Память, не освобожденная в конце потока#include <threads.h>
#include <stdlib.h>
/* Global key to the thread-specific storage */
tss_t key;
enum { MAX_THREADS = 3 };
int add_data(void) {
int *data = (int *)malloc(2 * sizeof(int));
if (data == NULL) {
return -1; /* Report error */
}
data[0] = 0;
data[1] = 1;
if (thrd_success != tss_set(key, (void *)data)) {
/* Handle error */
}
return 0;
}
void print_data(void) {
/* Get this thread's global data from key */
int *data = tss_get(key);
if (data != NULL) {
/* Print data */
}
}
int func(void *dummy) {
if (add_data() != 0) {
return -1; /* Report error */
}
print_data();
return 0;
}
int main(void) {
thrd_t thread_id[MAX_THREADS];
/* Create the key before creating the threads */
if (thrd_success != tss_create(&key, NULL)) {
/* Handle error */
}
/* Create threads that would store specific storage */
for (size_t i = 0; i < MAX_THREADS; i++) {
if (thrd_success != thrd_create(&thread_id[i], func, NULL)) {
/* Handle error */
}
}
for (size_t i = 0; i < MAX_THREADS; i++) {
if (thrd_success != thrd_join(thread_id[i], NULL)) {
/* Handle error */
}
}
tss_delete(key);
return 0;
}В этом примере стартовая функция каждого потока func вызывает две функции:
В точках, где func возвращает, динамически выделенное хранилище не освобождено.
Коррекция - свободная динамически выделенная память явным образомОдной из возможных коррекций является явное освобождение динамически выделенной памяти перед оставлением начальной функции потока. См. выделенное изменение в исправленной версии.
В этой исправленной версии дефект все еще появляется на return оператор в разделе обработки ошибок func. Дефект не может возникнуть на практике, потому что раздел обработки ошибок вводится только в случае сбоя динамического выделения памяти. Проигнорируйте этот оставшийся дефект с соответствующими комментариями. Смотрите Адрес Результаты Polyspace через исправления ошибок или обоснования.
#include <threads.h>
#include <stdlib.h>
/* Global key to the thread-specific storage */
tss_t key;
enum { MAX_THREADS = 3 };
int add_data(void) {
int *data = (int *)malloc(2 * sizeof(int));
if (data == NULL) {
return -1; /* Report error */
}
data[0] = 0;
data[1] = 1;
if (thrd_success != tss_set(key, (void *)data)) {
/* Handle error */
}
return 0;
}
void print_data(void) {
/* Get this thread's global data from key */
int *data = tss_get(key);
if (data != NULL) {
/* Print data */
}
}
int func(void *dummy) {
if (add_data() != 0) {
return -1; /* Report error */
}
print_data();
free(tss_get(key));
return 0;
}
int main(void) {
thrd_t thread_id[MAX_THREADS];
/* Create the key before creating the threads */
if (thrd_success != tss_create(&key, NULL)) {
/* Handle error */
}
/* Create threads that would store specific storage */
for (size_t i = 0; i < MAX_THREADS; i++) {
if (thrd_success != thrd_create(&thread_id[i], func, NULL)) {
/* Handle error */
}
}
for (size_t i = 0; i < MAX_THREADS; i++) {
if (thrd_success != thrd_join(thread_id[i], NULL)) {
/* Handle error */
}
}
tss_delete(key);
return 0;
}