在 malloc 之后 fork 导致内存泄漏
Fork after malloc causing memory leak
我正在从事一个需要分叉 N 个进程的系统编程项目。问题是我将 PID 保存在一个动态分配的数组中,并且带有“--leak-check=full --show-leak-kinds=all”标志的 valgrind 将此 PID 数组指针显示为可能的泄漏。
pid_t *pid;
//...globals & prototypes
int main(int argc, char *argv[])
{
//... Input parsing
// Create actor process=========================================
pid = malloc((_N + _V + _C + 1) * sizeof(pid_t *)); // LINE VALGRIND IS POINTING STILL REACHABLE
for (int i = 0; i < _N + _V + _C + 1; i++)
{
pid[i] = fork();
if (pid[i] == 0)
break;
}
// ======================================== Create actor process
// Parent process ====================================================
if (parent_pid == getpid())
{
// Wait for all the childeren=====================================
for (int i = 0; i < _N + _V + _C + 1 || exit_requested != 0; i++)
{
int status;
if (waitpid(pid[i], &status, 0) == -1)
{
errExit("waitpid");
}
}
// =====================================Wait for all the childeren
// Free resources
free(pid);
//.. destroy semaphores
shm_unlink(SHARED_LINK);
}
// Child processes ===================================================
else
{
for (int i = 0; i < _N + _V + _C + 1; i++)
{
if (i >= 0 && i < _N && pid[i] == 0)
{
producer(_I, shared_data, i);
}
else if (i >= _N && i < _N + _V && pid[i] == 0)
{
mid_consumer(shared_data, i - _N);
}
else if (i >= _N + _V && i < _N + _V + _C && pid[i] == 0)
{
end_consumer(shared_data, i - _N - _V);
}
}
}
// ===================================================================
return 0;
}
这是 valgrind 的输出
==8056== Memcheck, a memory error detector
==8056== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8056== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==8056== Command: ./program -n 2 -v 2 -c 4 -b 81 -t 2 -i cold_storage.txt
==8056== Parent PID: 8055
==8056==
==8061==
==8061== HEAP SUMMARY:
==8061== in use at exit: 72 bytes in 1 blocks
==8061== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8061==
==8061== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8061== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8061== by 0x10925D: main (main.c:169)
==8061==
==8061== LEAK SUMMARY:
==8061== definitely lost: 0 bytes in 0 blocks
==8061== indirectly lost: 0 bytes in 0 blocks
==8061== possibly lost: 0 bytes in 0 blocks
==8061== still reachable: 72 bytes in 1 blocks
==8061== suppressed: 0 bytes in 0 blocks
==8061==
==8061== For counts of detected and suppressed errors, rerun with: -v
==8061== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8059==
==8059== HEAP SUMMARY:
==8059== in use at exit: 72 bytes in 1 blocks
==8059== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8059==
==8057==
==8062==
==8057== HEAP SUMMARY:
==8057== in use at exit: 72 bytes in 1 blocks
==8057== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8057==
==8062== HEAP SUMMARY:
==8062== in use at exit: 72 bytes in 1 blocks
==8062== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8062==
==8059== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8059== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8059== by 0x10925D: main (main.c:169)
==8059==
==8059== LEAK SUMMARY:
==8059== definitely lost: 0 bytes in 0 blocks
==8059== indirectly lost: 0 bytes in 0 blocks
==8059== possibly lost: 0 bytes in 0 blocks
==8059== still reachable: 72 bytes in 1 blocks
==8059== suppressed: 0 bytes in 0 blocks
==8059==
==8059== For counts of detected and suppressed errors, rerun with: -v
==8059== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8062== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8057== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8062== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8057== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8062== by 0x10925D: main (main.c:169)
==8062==
==8057== by 0x10925D: main (main.c:169)
==8062== LEAK SUMMARY:
==8057==
==8062== definitely lost: 0 bytes in 0 blocks
==8057== LEAK SUMMARY:
==8062== indirectly lost: 0 bytes in 0 blocks
==8057== definitely lost: 0 bytes in 0 blocks
==8062== possibly lost: 0 bytes in 0 blocks
==8057== indirectly lost: 0 bytes in 0 blocks
==8062== still reachable: 72 bytes in 1 blocks
==8057== possibly lost: 0 bytes in 0 blocks
==8062== suppressed: 0 bytes in 0 blocks
==8057== still reachable: 72 bytes in 1 blocks
==8062==
==8057== suppressed: 0 bytes in 0 blocks
==8062== For counts of detected and suppressed errors, rerun with: -v
==8057==
==8062== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8057== For counts of detected and suppressed errors, rerun with: -v
==8057== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8063==
==8063== HEAP SUMMARY:
==8063== in use at exit: 72 bytes in 1 blocks
==8063== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8063==
==8063== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8063== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8063== by 0x10925D: main (main.c:169)
==8063==
==8063== LEAK SUMMARY:
==8063== definitely lost: 0 bytes in 0 blocks
==8063== indirectly lost: 0 bytes in 0 blocks
==8063== possibly lost: 0 bytes in 0 blocks
==8063== still reachable: 72 bytes in 1 blocks
==8063== suppressed: 0 bytes in 0 blocks
==8063==
==8063== For counts of detected and suppressed errors, rerun with: -v
==8063== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8058==
==8058== HEAP SUMMARY:
==8058== in use at exit: 72 bytes in 1 blocks
==8058== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8058==
==8058== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8058== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8058== by 0x10925D: main (main.c:169)
==8058==
==8058== LEAK SUMMARY:
==8058== definitely lost: 0 bytes in 0 blocks
==8058== indirectly lost: 0 bytes in 0 blocks
==8058== possibly lost: 0 bytes in 0 blocks
==8058== still reachable: 72 bytes in 1 blocks
==8058== suppressed: 0 bytes in 0 blocks
==8058==
==8058== For counts of detected and suppressed errors, rerun with: -v
==8058== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8064==
==8064== HEAP SUMMARY:
==8064== in use at exit: 72 bytes in 1 blocks
==8064== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8064==
==8064== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8064== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8064== by 0x10925D: main (main.c:169)
==8064==
==8064== LEAK SUMMARY:
==8064== definitely lost: 0 bytes in 0 blocks
==8064== indirectly lost: 0 bytes in 0 blocks
==8064== possibly lost: 0 bytes in 0 blocks
==8064== still reachable: 72 bytes in 1 blocks
==8064== suppressed: 0 bytes in 0 blocks
==8064==
==8064== For counts of detected and suppressed errors, rerun with: -v
==8064== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8060==
==8060== HEAP SUMMARY:
==8060== in use at exit: 72 bytes in 1 blocks
==8060== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8060==
==8060== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8060== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8060== by 0x10925D: main (main.c:169)
==8060==
==8060== LEAK SUMMARY:
==8060== definitely lost: 0 bytes in 0 blocks
==8060== indirectly lost: 0 bytes in 0 blocks
==8060== possibly lost: 0 bytes in 0 blocks
==8060== still reachable: 72 bytes in 1 blocks
==8060== suppressed: 0 bytes in 0 blocks
==8060==
==8060== For counts of detected and suppressed errors, rerun with: -v
==8060== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8065==
==8065== HEAP SUMMARY:
==8065== in use at exit: 72 bytes in 1 blocks
==8065== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8065==
==8065== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8065== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8065== by 0x10925D: main (main.c:169)
==8065==
==8065== LEAK SUMMARY:
==8065== definitely lost: 0 bytes in 0 blocks
==8065== indirectly lost: 0 bytes in 0 blocks
==8065== possibly lost: 0 bytes in 0 blocks
==8065== still reachable: 72 bytes in 1 blocks
==8065== suppressed: 0 bytes in 0 blocks
==8065==
==8065== For counts of detected and suppressed errors, rerun with: -v
==8065== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8056==
==8056== HEAP SUMMARY:
==8056== in use at exit: 0 bytes in 0 blocks
==8056== total heap usage: 1 allocs, 1 frees, 72 bytes allocated
==8056==
==8056== All heap blocks were freed -- no leaks are possible
==8056==
==8056== For counts of detected and suppressed errors, rerun with: -v
==8056== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我也试过在分叉进程中释放 PID 数组,但它仍然给出相同的错误。
这不是一个完整的答案,但它解决了一些问题。
首先,pid
数组内存块根据 sizeof(pid_t *)
的倍数分配了错误的大小,而它应该是 sizeof(pid_t)
的相同倍数。如果 sizeof(pid_t *)
大于 sizeof(pid_t)
,那是一种无害的内存浪费,但在 sizeof(pid_t *)
小于 sizeof(pid_t)
.[=25 的不同情况下,这将是缓冲区溢出=]
其次,子进程不释放pid
数组内存块。
第三,子进程循环遍历pid
数组内存块的所有元素寻找pid[i] == 0
。我相信这是试图找到自己索引的子进程。但是,pid
数组内存块在子进程 fork 中还没有完全初始化,因此可能存在多个值为 0
的元素。此外,子进程根本不需要使用 pid
数组,如果它所需要的只是它可以在 fork()
.
时确定的索引号
以下版本修复了这些问题,但我不知道它是否修复了 Valgrind 错误。
pid_t *pid;
//...globals & prototypes
int main(int argc, char *argv[])
{
int cid; // child index
//... Input parsing
// Create actor process=========================================
pid = malloc((_N + _V + _C + 1) * sizeof(pid_t));
for (cid = 0; xid < _N + _V + _C + 1; cid++)
{
pid[cid] = fork();
if (pid[cid] == 0)
{
free(pid);
break;
}
}
// ======================================== Create actor process
// Parent process ====================================================
if (parent_pid == getpid())
{
// Wait for all the childeren=====================================
for (int i = 0; i < _N + _V + _C + 1 || exit_requested != 0; i++)
{
int status;
if (waitpid(pid[i], &status, 0) == -1)
{
errExit("waitpid");
}
}
// =====================================Wait for all the childeren
// Free resources
free(pid);
//.. destroy semaphores
shm_unlink(SHARED_LINK);
}
// Child processes ===================================================
else
{
if (cid >= 0 && cid < _N)
{
producer(_I, shared_data, cid);
}
else if (cid >= _N && cid < _N + _V)
{
mid_consumer(shared_data, cid - _N);
}
else if (cid >= _N + _V && cid < _N + _V + _C)
{
end_consumer(shared_data, cid - _N - _V);
}
}
// ===================================================================
return 0;
}
我正在从事一个需要分叉 N 个进程的系统编程项目。问题是我将 PID 保存在一个动态分配的数组中,并且带有“--leak-check=full --show-leak-kinds=all”标志的 valgrind 将此 PID 数组指针显示为可能的泄漏。
pid_t *pid;
//...globals & prototypes
int main(int argc, char *argv[])
{
//... Input parsing
// Create actor process=========================================
pid = malloc((_N + _V + _C + 1) * sizeof(pid_t *)); // LINE VALGRIND IS POINTING STILL REACHABLE
for (int i = 0; i < _N + _V + _C + 1; i++)
{
pid[i] = fork();
if (pid[i] == 0)
break;
}
// ======================================== Create actor process
// Parent process ====================================================
if (parent_pid == getpid())
{
// Wait for all the childeren=====================================
for (int i = 0; i < _N + _V + _C + 1 || exit_requested != 0; i++)
{
int status;
if (waitpid(pid[i], &status, 0) == -1)
{
errExit("waitpid");
}
}
// =====================================Wait for all the childeren
// Free resources
free(pid);
//.. destroy semaphores
shm_unlink(SHARED_LINK);
}
// Child processes ===================================================
else
{
for (int i = 0; i < _N + _V + _C + 1; i++)
{
if (i >= 0 && i < _N && pid[i] == 0)
{
producer(_I, shared_data, i);
}
else if (i >= _N && i < _N + _V && pid[i] == 0)
{
mid_consumer(shared_data, i - _N);
}
else if (i >= _N + _V && i < _N + _V + _C && pid[i] == 0)
{
end_consumer(shared_data, i - _N - _V);
}
}
}
// ===================================================================
return 0;
}
这是 valgrind 的输出
==8056== Memcheck, a memory error detector
==8056== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8056== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==8056== Command: ./program -n 2 -v 2 -c 4 -b 81 -t 2 -i cold_storage.txt
==8056== Parent PID: 8055
==8056==
==8061==
==8061== HEAP SUMMARY:
==8061== in use at exit: 72 bytes in 1 blocks
==8061== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8061==
==8061== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8061== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8061== by 0x10925D: main (main.c:169)
==8061==
==8061== LEAK SUMMARY:
==8061== definitely lost: 0 bytes in 0 blocks
==8061== indirectly lost: 0 bytes in 0 blocks
==8061== possibly lost: 0 bytes in 0 blocks
==8061== still reachable: 72 bytes in 1 blocks
==8061== suppressed: 0 bytes in 0 blocks
==8061==
==8061== For counts of detected and suppressed errors, rerun with: -v
==8061== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8059==
==8059== HEAP SUMMARY:
==8059== in use at exit: 72 bytes in 1 blocks
==8059== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8059==
==8057==
==8062==
==8057== HEAP SUMMARY:
==8057== in use at exit: 72 bytes in 1 blocks
==8057== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8057==
==8062== HEAP SUMMARY:
==8062== in use at exit: 72 bytes in 1 blocks
==8062== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8062==
==8059== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8059== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8059== by 0x10925D: main (main.c:169)
==8059==
==8059== LEAK SUMMARY:
==8059== definitely lost: 0 bytes in 0 blocks
==8059== indirectly lost: 0 bytes in 0 blocks
==8059== possibly lost: 0 bytes in 0 blocks
==8059== still reachable: 72 bytes in 1 blocks
==8059== suppressed: 0 bytes in 0 blocks
==8059==
==8059== For counts of detected and suppressed errors, rerun with: -v
==8059== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8062== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8057== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8062== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8057== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8062== by 0x10925D: main (main.c:169)
==8062==
==8057== by 0x10925D: main (main.c:169)
==8062== LEAK SUMMARY:
==8057==
==8062== definitely lost: 0 bytes in 0 blocks
==8057== LEAK SUMMARY:
==8062== indirectly lost: 0 bytes in 0 blocks
==8057== definitely lost: 0 bytes in 0 blocks
==8062== possibly lost: 0 bytes in 0 blocks
==8057== indirectly lost: 0 bytes in 0 blocks
==8062== still reachable: 72 bytes in 1 blocks
==8057== possibly lost: 0 bytes in 0 blocks
==8062== suppressed: 0 bytes in 0 blocks
==8057== still reachable: 72 bytes in 1 blocks
==8062==
==8057== suppressed: 0 bytes in 0 blocks
==8062== For counts of detected and suppressed errors, rerun with: -v
==8057==
==8062== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8057== For counts of detected and suppressed errors, rerun with: -v
==8057== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8063==
==8063== HEAP SUMMARY:
==8063== in use at exit: 72 bytes in 1 blocks
==8063== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8063==
==8063== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8063== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8063== by 0x10925D: main (main.c:169)
==8063==
==8063== LEAK SUMMARY:
==8063== definitely lost: 0 bytes in 0 blocks
==8063== indirectly lost: 0 bytes in 0 blocks
==8063== possibly lost: 0 bytes in 0 blocks
==8063== still reachable: 72 bytes in 1 blocks
==8063== suppressed: 0 bytes in 0 blocks
==8063==
==8063== For counts of detected and suppressed errors, rerun with: -v
==8063== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8058==
==8058== HEAP SUMMARY:
==8058== in use at exit: 72 bytes in 1 blocks
==8058== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8058==
==8058== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8058== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8058== by 0x10925D: main (main.c:169)
==8058==
==8058== LEAK SUMMARY:
==8058== definitely lost: 0 bytes in 0 blocks
==8058== indirectly lost: 0 bytes in 0 blocks
==8058== possibly lost: 0 bytes in 0 blocks
==8058== still reachable: 72 bytes in 1 blocks
==8058== suppressed: 0 bytes in 0 blocks
==8058==
==8058== For counts of detected and suppressed errors, rerun with: -v
==8058== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8064==
==8064== HEAP SUMMARY:
==8064== in use at exit: 72 bytes in 1 blocks
==8064== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8064==
==8064== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8064== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8064== by 0x10925D: main (main.c:169)
==8064==
==8064== LEAK SUMMARY:
==8064== definitely lost: 0 bytes in 0 blocks
==8064== indirectly lost: 0 bytes in 0 blocks
==8064== possibly lost: 0 bytes in 0 blocks
==8064== still reachable: 72 bytes in 1 blocks
==8064== suppressed: 0 bytes in 0 blocks
==8064==
==8064== For counts of detected and suppressed errors, rerun with: -v
==8064== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8060==
==8060== HEAP SUMMARY:
==8060== in use at exit: 72 bytes in 1 blocks
==8060== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8060==
==8060== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8060== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8060== by 0x10925D: main (main.c:169)
==8060==
==8060== LEAK SUMMARY:
==8060== definitely lost: 0 bytes in 0 blocks
==8060== indirectly lost: 0 bytes in 0 blocks
==8060== possibly lost: 0 bytes in 0 blocks
==8060== still reachable: 72 bytes in 1 blocks
==8060== suppressed: 0 bytes in 0 blocks
==8060==
==8060== For counts of detected and suppressed errors, rerun with: -v
==8060== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8065==
==8065== HEAP SUMMARY:
==8065== in use at exit: 72 bytes in 1 blocks
==8065== total heap usage: 1 allocs, 0 frees, 72 bytes allocated
==8065==
==8065== 72 bytes in 1 blocks are still reachable in loss record 1 of 1
==8065== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8065== by 0x10925D: main (main.c:169)
==8065==
==8065== LEAK SUMMARY:
==8065== definitely lost: 0 bytes in 0 blocks
==8065== indirectly lost: 0 bytes in 0 blocks
==8065== possibly lost: 0 bytes in 0 blocks
==8065== still reachable: 72 bytes in 1 blocks
==8065== suppressed: 0 bytes in 0 blocks
==8065==
==8065== For counts of detected and suppressed errors, rerun with: -v
==8065== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==8056==
==8056== HEAP SUMMARY:
==8056== in use at exit: 0 bytes in 0 blocks
==8056== total heap usage: 1 allocs, 1 frees, 72 bytes allocated
==8056==
==8056== All heap blocks were freed -- no leaks are possible
==8056==
==8056== For counts of detected and suppressed errors, rerun with: -v
==8056== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我也试过在分叉进程中释放 PID 数组,但它仍然给出相同的错误。
这不是一个完整的答案,但它解决了一些问题。
首先,pid
数组内存块根据 sizeof(pid_t *)
的倍数分配了错误的大小,而它应该是 sizeof(pid_t)
的相同倍数。如果 sizeof(pid_t *)
大于 sizeof(pid_t)
,那是一种无害的内存浪费,但在 sizeof(pid_t *)
小于 sizeof(pid_t)
.[=25 的不同情况下,这将是缓冲区溢出=]
其次,子进程不释放pid
数组内存块。
第三,子进程循环遍历pid
数组内存块的所有元素寻找pid[i] == 0
。我相信这是试图找到自己索引的子进程。但是,pid
数组内存块在子进程 fork 中还没有完全初始化,因此可能存在多个值为 0
的元素。此外,子进程根本不需要使用 pid
数组,如果它所需要的只是它可以在 fork()
.
以下版本修复了这些问题,但我不知道它是否修复了 Valgrind 错误。
pid_t *pid;
//...globals & prototypes
int main(int argc, char *argv[])
{
int cid; // child index
//... Input parsing
// Create actor process=========================================
pid = malloc((_N + _V + _C + 1) * sizeof(pid_t));
for (cid = 0; xid < _N + _V + _C + 1; cid++)
{
pid[cid] = fork();
if (pid[cid] == 0)
{
free(pid);
break;
}
}
// ======================================== Create actor process
// Parent process ====================================================
if (parent_pid == getpid())
{
// Wait for all the childeren=====================================
for (int i = 0; i < _N + _V + _C + 1 || exit_requested != 0; i++)
{
int status;
if (waitpid(pid[i], &status, 0) == -1)
{
errExit("waitpid");
}
}
// =====================================Wait for all the childeren
// Free resources
free(pid);
//.. destroy semaphores
shm_unlink(SHARED_LINK);
}
// Child processes ===================================================
else
{
if (cid >= 0 && cid < _N)
{
producer(_I, shared_data, cid);
}
else if (cid >= _N && cid < _N + _V)
{
mid_consumer(shared_data, cid - _N);
}
else if (cid >= _N + _V && cid < _N + _V + _C)
{
end_consumer(shared_data, cid - _N - _V);
}
}
// ===================================================================
return 0;
}