C:fork()动态内存分配 请考虑下面的代码片段: 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); }

C:fork()动态内存分配 请考虑下面的代码片段: 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); },c,memory-leaks,dynamic-memory-allocation,C,Memory Leaks,Dynamic Memory Allocation,输出: 任务数组:[11489296] 主要信息:[21060]:[11489296][7] 家长:[21060]:[11489296][7] 儿童:[21061]:[11489296][7] 儿童:[21061]:[11489296][10] 家长:[21060]:[11489296][7] 家长:[21060]:[11489328][] 请帮我确认/理解以下几点 指针地址是虚拟的,因此即使地址看起来相同,子级和父级也有不同的值 子级中的free()释放分配给子级的内存,不影响分配给父级

输出:

  • 任务数组:[11489296]
  • 主要信息:[21060]:[11489296][7]
  • 家长:[21060]:[11489296][7]
  • 儿童:[21061]:[11489296][7]
  • 儿童:[21061]:[11489296][10]
  • 家长:[21060]:[11489296][7]
  • 家长:[21060]:[11489328][]
请帮我确认/理解以下几点

  • 指针地址是虚拟的,因此即使地址看起来相同,子级和父级也有不同的值
  • 子级中的free()释放分配给子级的内存,不影响分配给父级的内存
  • 在calloc中,我只分配了1项,但我尝试使用[1000],它仍然有效,因为即使没有分配给我,内存仍然存在。然而,它的风险很大,将来可能会导致堆芯转储。类似地,在child中,我使用free()后的内存,它仍然有效
  • 在父级中,我有大量内存泄漏,因为没有空闲()。如果程序一直在循环中运行,直到有人终止进程,请帮助理解内存泄漏的副作用。另外,请告知进程被终止时会发生什么情况,是否释放了所有内存
编辑:


我知道很多行为都是未定义的,代码在逻辑上并不正确,但它仍然可以工作并执行。问题是试图理解为什么会出现格式错误、逻辑错误的代码以及为什么。

您应该记住,在“C”课程中,
fork
通过复制虚拟分页表创建了一个新的进程,这样子进程将看到与父进程完全相同的值(通常这些页将具有只读保护). 但是,一旦您开始在子内存空间中写入,相应页面条目的物理映射将更新为指向新位置,并且数据将复制到新位置

指针地址是虚拟的,因此即使地址看起来相同,子级和父级也有不同的值

  • virtual
    地址看起来是一样的,尽管它们的物理映射可能不同,是的,值也会不同
子级中的free()释放分配给子级的内存,不影响分配给父级的内存

  • 是的,它不会影响父级,因为它将在子级的虚拟空间和该空间的子级物理映射中完成。Free-only表示操作内存中的指针。因此,释放节点的内容仍然可以映射到父空间(直到您开始覆盖它)
在calloc中,我只分配了1项,但我尝试使用[1000],它仍然有效,因为即使没有分配给我,内存仍然存在。然而,它的风险很大,将来可能会导致堆芯转储。类似地,在child中,我使用free()后的内存,它仍然有效

  • 不要您只是从内存中读取了一些值,而这些值并不是您所认为的值(即使是合法的),或者通过编写来破坏它。不管是孩子还是父母
在父级中,我有大量内存泄漏,因为没有空闲()。如果程序一直在循环中运行,直到有人终止进程,请帮助理解内存泄漏的副作用。另外,请告知进程被终止时会发生什么情况,是否释放了所有内存

  • 当一个被处理的进程以任何方式被终止或正常退出时,它使用的所有内存通常都会返回到操作系统以供重用。至少在我所知道的所有通用操作系统中
技术上,
printf(“\ntaskArray:[%d]\n”,taskArray)是UB。检查其余部分没有意义,除非您解决了这个(或这些)。基本上,是/是/是/是。使用所有警告和调试信息编译(因此
gcc-Wall-Wextra-g
with…)。然后使用调试器并使用@SouravGhosh好的,我明白你的意思了。我们需要打印带有%p@pOrinG的指针。分析未定义的“工作”的“原因”是毫无意义的。它没有在你注意到的事情上失败,这和知道它有效不是一回事。这不正确,这是一个错误。它可能不会崩溃,但不能保证它会崩溃。该行为未定义,必须在工作代码中避免。感谢您的回复。我曾看到人们谈论过forked进程使用的写上拷贝。从那以后,父对象和子对象实际上指向同一个位置,直到我更改了正确的位置为止?所以我想了解与free的互动。当我释放子级中的指针时,它是否释放并将空间从父级和子级返回到内存分配器,或者父级仍然保留分配的内存?我也不理解这一点:
free只意味着操作内存中的指针。因此,释放节点的内容仍然可以映射到父空间(直到您开始覆盖它)。
@poring Malloc/free通常通过操作空闲/忙碌内存块列表来工作。@poring-当您调用
free(x)
时,您说的是“我将不再使用内存x”,内存管理器会记下这一点。这就是全部。如果你仍然使用x,你就只能靠自己了,任何事情都有可能发生——包括x还在那里一段时间。@BoPersson好的,我知道了。事实上,我能够分别在父级和子级中释放(x)这一事实告诉我,内存是被分配的,因为如果你试图在一个进程中释放一些没有分配给你的东西,它会产生核心转储,或者如果你释放它两次,它会产生双重释放或损坏。对的