求大佬解释下谢谢
#include <sys_head.h>//自定义头文件已包含下列代码中使用的函数所需头文件int *ptr;
void END(void)
{
if (NULL != ptr)
{
printf("\n");
for (int i = 0; i < 10; i++)
{
printf("%d\t", ptr);
}
free(ptr);
printf("\n内存释放成功\n");
}
}
int main(int argc, char *argv[])
{
ptr = (int *)malloc(sizeof(int) * 10);
if (NULL == ptr)
{
ERRLOG("内存分配失败");
return EOF;
}
memset(ptr, 0, sizeof(int) * 10);
for (int i = 0; i < 10; i++)
{
printf("请输入一个整数:");
scanf("%d", &ptr);
}
for (int i = 0; i < 10; i++)
{
printf("%d\t", ptr);
}
int pid = fork();
if (pid == 0)
{
atexit(END); // 注册退出函数
}
else if (pid > 0)
{
printf("\n我是父进程我的子进程的pid是%d\n", pid);
}
return 0;
屏幕输出内容如下:
请输入一个整数:1
请输入一个整数:2
请输入一个整数:3
请输入一个整数:4
请输入一个整数:5
请输入一个整数:6
请输入一个整数:7
请输入一个整数:8
请输入一个整数:9
请输入一个整数:10
1 2 3 4 5 6 7 8 9 10
我是父进程我的子进程的pid是14838
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
内存释放成功
问为什么执行子进程打印了2变数组的内容?
你的代码中有几个问题,导致子进程输出不符合预期。下面我对代码中一些关键的地方进行解释:
1. **错误地访问指针数组**:
scanf("%d", &ptr);
这里应该是 `scanf("%d", &ptr);`,表示将用户输入的整数存储到 `ptr` 指向的数组中。当前代码每次输入都会将值写入指针 `ptr` 的地址,导致未在数组中存储任何值。
2. **错误地打印数组内容**:
for (int i = 0; i < 10; i++) {
printf("%d\t", ptr);
}
应该是 `printf("%d\t", ptr);`,这样才能逐个打印数组元素,而不是重复打印指针地址的值。
3. **子进程的输出**:
由于子进程直接从父进程的内存空间复制而来,所以执行 `atexit(END);` 之后会在子进程结束时输出一次数组和释放内存信息。这是为什么你看到两个输出的原因,但实际内容并未按照你期望地存储和打印。
因此,当你修正输入和输出的数组索引问题后,代码应该只正确输出一次数组内容,子进程和父进程会分别输出。(每个进程都应用同样的内存,在每次输入时都应该检查和验证内存操作是否如预期执行。)
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-10-15 20:21
你的代码中有几个问题,导致子进程输出不符合预期。下面我对代码中一些关键的地方进行解释:
1. **错误 ...
你这错误看错了把,我这打印和获取变量都是对的呀
主要让你解释执行子进程为啥会打印2个数组信息,内存释放成功这条文本又只执行一次
轻语远歌 发表于 2024-10-15 20:25
你这错误看错了把,我这打印和获取变量都是对的呀
主 ...
非常抱歉刚才的解答没能准确针对你的问题。
解释执行结果:
1. **子进程与父进程的区别**:
当调用 `fork()` 时,子进程会复制父进程的整个内存空间。因此,子进程里的 `ptr` 和父进程里的 `ptr` 指向的是相同的数据内容,但处于各自进程的内存空间中。
2. **`atexit(END)`的影响**:
你在子进程中注册了 `END` 函数,意味着子进程结束时会调用 `END`。因此,子进程在结束时会打印一次数组并释放它自己的 `ptr` 指向的内存。
3. **父进程的输出**:
父进程并没有注册 `atexit(END)`,所以在父进程正常结束时并没有执行 `END`,只会输出子进程创建和相关信息。
4. **内存释放的现象**:
“内存释放成功”仅输出一次是因为只有子进程调用了 `END` 函数。父进程没有注册这个函数,自然也就不会打印“内存释放成功”。注意,因为父进程终止时操作系统自动回收资源,所以不影响整体资源管理。
综上,由于 `fork()` 复制进程后,两个进程各自有一份独立的 `ptr`,所以在子进程结束时看到两次数组打印信息和一次内存释放信息。通过理解 `fork()` 的复制机制和 `atexit()` 的注册机制,可以清楚地解答这种行为。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-10-15 20:26
非常抱歉刚才的解答没能准确针对你的问题。
解释执行结果:
还是不太理解数组内容是怎末打印了2次,这2次内容是那个进程打印的,若都是子进程打印那不应该都是打印2次吗 轻语远歌 发表于 2024-10-15 20:32
还是不太理解数组内容是怎末打印了2次,这2次内容是那 ...
非常抱歉之前解释不够清晰。
在你的代码中,对于为什么子进程打印了两次数组内容,可以通过以下细节来解释:
1. **子进程的执行**:
- `atexit(END);` 注册了 `END` 函数,当子进程结束时,`END` 函数会被调用。
- 子进程继承了父进程的整个内存空间和文件指针,所以它们都持有 `ptr` 的相同引用。当子进程运行完自己的代码块并在 `return 0;` (或进程正常退出)前,`atexit` 注册的 `END` 函数会被调用。
2. **END 函数被调用的次数**:
- 由于在子进程中注册并调用了 `END` 函数,导致子进程退出时调用 `END`,从而打印数组内容。
- 因此,子进程会调用 `END` 一次,并在 `END` 中打印一次数组内容。
3. **内存释放的次数**:
- 由于 `END` 在子进程中被调用且 `ptr` 只在子进程的地址空间被释放一次,而父进程并没有调用 `END`,因此 "内存释放成功" 只被输出一次。
总结:子进程调用了 `END`,因此输出了数组两次,而"内存释放成功"也是在子进程中执行的,由于没有在父进程注册 `END`,父进程没有额外的输出。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-10-15 20:43
非常抱歉之前解释不够清晰。
在你的代码中,对于为什么子进程打印了两次数组内容,可以通过以下细节 ...
如果子进程调用了2次END()函数那么内存释放成功不应该要打印2次吗?
轻语远歌 发表于 2024-10-15 20:51
如果子进程调用了2次END()函数那么内存释放成功不应该 ...
抱歉之前没有解释清楚。实际上,子进程只调用了一次 `END()` 函数。我们来看过程:
1. **子进程的退出行为**:
- `atexit(END);` 只会在正常退出时调用 `END()` 函数一次。
- 子进程和父进程实际上都有各自独立的 `ptr` 副本,但 `free(ptr);` 只应用于调用它的进程(在这里是子进程)。
2. **子进程打印两次数组内容**:
- `fork()` 产生的子进程会从父进程中完全复制一份,因此最开始时候子进程里此时 `ptr` 的内容与父进程的一样。
- 第一次打印数组内容是在你已经输入完数据之后立刻显示(直接在 `scanf` 后面的循环),这每次都由子进程和父进程执行。
- 第二次是当子进程退出时,`atexit` 调用了 `END` 函数来打印数组并释放内存,因此子进程最终把数组内容和内存释放提示打印出来。
总结来说,第一次打印来自于 `main` 中的循环,第二次打印来自于 `END` 函数。子进程的 `END` 函数只调用了一次,所以内存释放的提示信息也只打印一次。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-10-15 20:51
抱歉之前没有解释清楚。实际上,子进程只调用了一次 `END()` 函数。我们来看过程:
1. **子进程的退 ...
数组的内容一共打印了3次呀,第一次是在子进程没有创建前打印的,在打印我是父进程我的子进程ID是这一行文本下面的一行数组内容是如何打印出来的,fock()创建子进程不是主进程和子进程都是执行fock()以下的代码内容吗? 轻语远歌 发表于 2024-10-15 20:58
数组的内容一共打印了3次呀,第一次是在子进程没有创 ...
你说得没错,`fork()` 后,父进程和子进程都会继续执行 `fork()` 之后的代码。
在你的代码中,数组内容打印三次的情况如下:
1. **第一次打印**:在 `fork()` 之前,`main` 函数中的循环打印出数组内容。
2. **第二次打印**:子进程创建后,会从 `fork()` 之后继续执行,因为子进程继承了父进程的内存空间,所以它会打印一次数组内容以及 "我是父进程..." 的信息。
3. **第三次打印**:子进程退出时调用注册在 `atexit` 的 `END` 函数,再次打印数组内容,并释放内存。
对子进程而言,在 `fork()` 之后代码继续执行,并由于 `atexit` 注册的 `END` 函数,导致数组内容和 "内存释放成功" 各打印一次。对于父进程,它只在 `fork()` 之后打印了一次 "我是父进程…" 的信息。
这样的执行顺序确实可以导致在你所看到的程序输出中,数组内容被打印三次,但因具体环境差异,第二次和第三次可能顺序有所不同。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]