C: fork() 动态内存分配
C: fork() dynamic memory allocation
请考虑以下代码片段:
struct TASKS {char taskid[4];};
struct TASKS *taskArray;
int main()
{
for(;;)
{
taskArray = (struct TASKS *) calloc(1, sizeof(struct TASKS));
printf("\ntaskArray:[%d]\n",taskArray);fflush(stdout);
strcpy(taskArray[1000].taskid,"7");
printf("main:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
returnvalue = fork();
if (returnvalue == 0)
{
printf("Child:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
free(taskArray);
strcpy(taskArray[1000].taskid,"10");
sleep(3);
printf("Child:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
exit(1);
}
if (returnvalue != 0)
{
printf("Parent:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
sleep(6);
printf("Parent:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
taskArray = (struct TASKS *) calloc(1, sizeof(struct TASKS));
printf("Parent:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
}
}
exit(1);
}
输出:
- 任务数组:[11489296]
- 主要:[21060]:[11489296][7]
- Parent:[21060] : [11489296][7]
- Child:[21061] : [11489296][7]
- Child:[21061] : [11489296][10]
- Parent:[21060] : [11489296][7]
- Parent:[21060] : [11489328][]
请帮我confirm/understand以下要点
- 指针地址是虚拟的,因此即使地址看起来相同,child 和 parent 也有不同的值。
- free() in child 释放分配给 child 的内存并且不影响分配给 parent.
的内存
- 在 calloc 中,我只分配了 1 个项目,但是我正在尝试使用 [1000],它仍然有效,因为即使没有分配给我,内存仍然存在。然而,它有风险并且将来可能会导致核心转储。类似地,在 child 中,我在 free() 之后使用内存,它仍然有效。
- 在 parent 中,由于没有 free(),我有大量内存泄漏。如果程序一直循环运行直到有人终止进程,请帮助理解此内存泄漏的副作用。另外请告知当进程被终止时会发生什么,它会释放所有内存吗?
编辑:
我知道许多行为是未定义的,代码在逻辑上不正确,但它仍然可以运行并执行。问题是关于试图理解 ill-formed、ill-logical 代码为何有效以及原因。
你应该记得在 'C' 课程中 fork
通过复制虚拟分页 table 创建了一个新进程,所以 child 会看到完全相同的值为 parent(通常页面将具有 read-only 保护)。然而,一旦您开始在 child 内存 space 中写入,相应页面条目的物理映射将更新为指向新位置,并且数据将被复制到新位置。
指针地址是虚拟的,因此即使地址看起来相同,child 和 parent 也有不同的值。
virtual
地址看起来一样,尽管它们的物理映射可能不同,而且,是的,值会不同。
free() in child 释放分配给 child 的内存并且不影响分配给 parent.[ 的内存=12=]
- 是的,它不会影响 parent,因为它将在 child 的虚拟 space 和 child 的物理映射中完成 space。 free only是指在内存中操作指针。因此,释放节点的内容仍然可以映射到 parent space(直到你开始覆盖它)。
在 calloc 中,我只分配了 1 个项目,但是我正在尝试使用 [1000],它仍然有效,因为即使没有分配给我,内存仍然存在。然而,它有风险并且将来可能会导致核心转储。同样,在 child 中,我在 free() 之后使用内存,它仍然有效。
- 不要!! 你只是从内存中读取值,这不是你认为的值,即使合法,或者通过写入破坏它。不管是 child 还是 parent.
在 parent 中,由于没有 free(),我有大量内存泄漏。如果程序一直循环运行直到有人终止进程,请帮助理解此内存泄漏的副作用。另外请告知当进程被终止时会发生什么,它会释放所有内存吗?
- 当一个进程被以任何方式杀死或正常退出时,它使用的所有内存通常都会返回给 OS 以供重用。至少在我所知道的所有通用 OS 中。
请考虑以下代码片段:
struct TASKS {char taskid[4];};
struct TASKS *taskArray;
int main()
{
for(;;)
{
taskArray = (struct TASKS *) calloc(1, sizeof(struct TASKS));
printf("\ntaskArray:[%d]\n",taskArray);fflush(stdout);
strcpy(taskArray[1000].taskid,"7");
printf("main:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
returnvalue = fork();
if (returnvalue == 0)
{
printf("Child:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
free(taskArray);
strcpy(taskArray[1000].taskid,"10");
sleep(3);
printf("Child:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
exit(1);
}
if (returnvalue != 0)
{
printf("Parent:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
sleep(6);
printf("Parent:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
taskArray = (struct TASKS *) calloc(1, sizeof(struct TASKS));
printf("Parent:[%d] : [%d][%s]\n",getpid(),taskArray,taskArray[1000].taskid);fflush(stdout);
}
}
exit(1);
}
输出:
- 任务数组:[11489296]
- 主要:[21060]:[11489296][7]
- Parent:[21060] : [11489296][7]
- Child:[21061] : [11489296][7]
- Child:[21061] : [11489296][10]
- Parent:[21060] : [11489296][7]
- Parent:[21060] : [11489328][]
请帮我confirm/understand以下要点
- 指针地址是虚拟的,因此即使地址看起来相同,child 和 parent 也有不同的值。
- free() in child 释放分配给 child 的内存并且不影响分配给 parent. 的内存
- 在 calloc 中,我只分配了 1 个项目,但是我正在尝试使用 [1000],它仍然有效,因为即使没有分配给我,内存仍然存在。然而,它有风险并且将来可能会导致核心转储。类似地,在 child 中,我在 free() 之后使用内存,它仍然有效。
- 在 parent 中,由于没有 free(),我有大量内存泄漏。如果程序一直循环运行直到有人终止进程,请帮助理解此内存泄漏的副作用。另外请告知当进程被终止时会发生什么,它会释放所有内存吗?
编辑:
我知道许多行为是未定义的,代码在逻辑上不正确,但它仍然可以运行并执行。问题是关于试图理解 ill-formed、ill-logical 代码为何有效以及原因。
你应该记得在 'C' 课程中 fork
通过复制虚拟分页 table 创建了一个新进程,所以 child 会看到完全相同的值为 parent(通常页面将具有 read-only 保护)。然而,一旦您开始在 child 内存 space 中写入,相应页面条目的物理映射将更新为指向新位置,并且数据将被复制到新位置。
指针地址是虚拟的,因此即使地址看起来相同,child 和 parent 也有不同的值。
virtual
地址看起来一样,尽管它们的物理映射可能不同,而且,是的,值会不同。
free() in child 释放分配给 child 的内存并且不影响分配给 parent.[ 的内存=12=]
- 是的,它不会影响 parent,因为它将在 child 的虚拟 space 和 child 的物理映射中完成 space。 free only是指在内存中操作指针。因此,释放节点的内容仍然可以映射到 parent space(直到你开始覆盖它)。
在 calloc 中,我只分配了 1 个项目,但是我正在尝试使用 [1000],它仍然有效,因为即使没有分配给我,内存仍然存在。然而,它有风险并且将来可能会导致核心转储。同样,在 child 中,我在 free() 之后使用内存,它仍然有效。
- 不要!! 你只是从内存中读取值,这不是你认为的值,即使合法,或者通过写入破坏它。不管是 child 还是 parent.
在 parent 中,由于没有 free(),我有大量内存泄漏。如果程序一直循环运行直到有人终止进程,请帮助理解此内存泄漏的副作用。另外请告知当进程被终止时会发生什么,它会释放所有内存吗?
- 当一个进程被以任何方式杀死或正常退出时,它使用的所有内存通常都会返回给 OS 以供重用。至少在我所知道的所有通用 OS 中。