#c #pointers #malloc #valgrind #free
#c #указатели #malloc #valgrind #Бесплатно
Вопрос:
Я хотел бы реализовать приложение, которое отвечает за параллельное выполнение нескольких задач.
Перед добавлением реальных задач я попытался установить базу, но программа возвращает различные ошибки при выполнении valgrind.
==4827== Thread 3:
==4827== Invalid free() / delete / delete[] / realloc()
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Address 0x5420070 is 48 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827== Thread 1:
==4827== Invalid read of size 8
==4827== at 0x400CD3: main (in /home/test)
==4827== Address 0x5420068 is 40 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827== Invalid read of size 8
==4827== at 0x400CFF: main (in /home/test)
==4827== Address 0x5420068 is 40 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827== Invalid read of size 8
==4827== at 0x400D30: main (in /home/test)
==4827== Address 0x5420060 is 32 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
tstop
==4827== Invalid write of size 8
==4827== at 0x400D5B: main (in /home/test)
==4827== Address 0x5420068 is 40 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
tstop
==4827== Invalid free() / delete / delete[] / realloc()
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400D8C: main (in /home/test)
==4827== Address 0x5420040 is 0 bytes inside a block of size 96 free'd
==4827== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400E31: my_handler (in /home/test)
==4827== by 0x4E416F9: start_thread (pthread_create.c:333)
==4827== Block was alloc'd at
==4827== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4827== by 0x400B75: main (in /home/test)
==4827==
==4827==
==4827== HEAP SUMMARY:
==4827== in use at exit: 1,614 bytes in 4 blocks
==4827== total heap usage: 9 allocs, 7 frees, 3,334 bytes allocated
==4827==
==4827== LEAK SUMMARY:
==4827== definitely lost: 0 bytes in 0 blocks
==4827== indirectly lost: 0 bytes in 0 blocks
==4827== possibly lost: 0 bytes in 0 blocks
==4827== still reachable: 1,614 bytes in 4 blocks
==4827== suppressed: 0 bytes in 0 blocks
Я предполагаю, что эти ошибки связаны с доступом к памяти, которая уже освобождена, и недопустимым free().
Однако я не могу понять, как и почему они происходят.
typedef int (*init)();
typedef int (*launch)();
typedef int (*stop)();
typedef struct stTask stTask_t;
typedef struct stEngine stEngine_t;
struct stTask
{
char name[10];
init initTask;
launch launchTask;
stop stopTask;
pthread_t tId;
};
struct stEngine
{
int16_t NbTasks;
stTask_t* TaskThread;
};
static void sig_handler(int signo);
static int tinit(void);
static int tlaunch(void);
static int tstop(void);
static void* my_handler(void* params);
stTask_t array[] =
{
{"TEST", (init)tinit, (launch)tlaunch, (stop)tstop, 0},
{"TEST2", (init)tinit, (launch)tlaunch, (stop)tstop, 0}
};
int exitReq;
stEngine_t engine;
int main (int argc, char *argv[])
{
struct sigaction action;
int i;
exitReq = 0;
memset(amp;engine, 0, sizeof(stEngine_t));
engine.NbTasks = 2;
memset(amp;action, '', sizeof(action));
action.sa_handler = amp;sig_handler;
sigfillset(amp;action.sa_mask);
action.sa_flags = 0;
if ((sigaction(SIGTERM, amp;action, NULL) != 0) || (sigaction(SIGINT, amp;action, NULL) != 0)) {
exit(EXIT_FAILURE);
}
engine.TaskThread = malloc(engine.NbTasks * sizeof(stTask_t));
for (i = 0; i < engine.NbTasks; i ) {
engine.TaskThread[i] = array[i];
engine.TaskThread[i].initTask();
pthread_create(amp;engine.TaskThread[i].tId, NULL, my_handler, (void *) amp;engine.TaskThread[i]);
}
while (!exitReq) {
//... do stuff
sched_yield();
}
for (i = 0; i < engine.NbTasks; i ) {
(void)pthread_cancel(engine.TaskThread[i].tId);
pthread_join(engine.TaskThread[i].tId, NULL);
engine.TaskThread[i].stopTask();
engine.TaskThread[i].tId = 0;
}
free(engine.TaskThread);
memset(amp;engine, 0, sizeof(stEngine_t));
return 0;
}
static void sig_handler(int signo)
{
if (signo == SIGINT || signo == SIGTERM) {
exitReq = 1;
}
}
static void* my_handler(void* params)
{
stTask_t* ptask = (stTask_t*) params;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
while (!exitReq) {
ptask->launchTask();
pthread_testcancel();
}
free(ptask);
pthread_exit(NULL);
}
static int tinit(void)
{
fprintf(stdout, "%sn", __func__);
return 0;
}
static int tlaunch(void)
{
fprintf(stdout, "%sn", __func__);
return 0;
}
static int tstop(void)
{
fprintf(stdout, "%sn", __func__);
return 0;
}
Добавив комментарий в функцию обработки: я не получил ошибки, но несколько байтов все еще выделяются при ручной остановке программы.
//free(ptask);
Я не получаю ошибки, но при ручной остановке программы все еще выделяется несколько байтов.
По мере необходимости я передаю адрес структуры в качестве последнего параметра pthread_create, но, вероятно, я что-то неправильно понимаю в памяти
==6017== HEAP SUMMARY:
==6017== in use at exit: 1,614 bytes in 4 blocks
==6017== total heap usage: 9 allocs, 5 frees, 3,334 bytes allocated
==6017==
==6017== LEAK SUMMARY:
==6017== definitely lost: 0 bytes in 0 blocks
==6017== indirectly lost: 0 bytes in 0 blocks
==6017== possibly lost: 0 bytes in 0 blocks
==6017== still reachable: 1,614 bytes in 4 blocks
==6017== suppressed: 0 bytes in 0 blocks
Может ли кто-нибудь объяснить мне, почему в обоих случаях память освобождается неправильно?
Комментарии:
1. Вы выполняете один
malloc
(в основном) для выделения массива, а затем множествоfree
вызовов (в дочерних потоках) для каждого элемента в выделенном массиве. Это неверно. Каждыйmalloc
должен иметь ровно один,free
и этомуfree
должно быть присвоено точное значение, возвращаемоеmalloc
. Кроме того, основной поток также освобождает весь массив. Так что это тоже двойное освобождение.2. @kaylum Спасибо! Кажется, это решает проблему