【问题标题】:Referencing pointers after a fork() call in C在 C 中的 fork() 调用之后引用指针
【发布时间】:2010-12-09 01:02:50
【问题描述】:

所以,我有一个函数可以加载带有一些字符串数据的 char** 变量。我的目标是分叉这个过程,并在子进程中打印一些数据,以及从父进程中打印一些数据。但是,我无法在 fork() 调用之后引用指针。

我以为fork()复制了父进程的整个地址空间,好像里面会包含各种栈指针……

基本上,我的代码目前看起来像这样:

load_data(char **data);

char** data;
load_data(data);
printf("String 0: %s\n", data[0]);
fork(); 
printf("String 0 again: %s\n", data[0]);    /* Segfaults Here! */

有人知道我做错了什么吗?我已经对此进行了一些谷歌搜索,似乎我正在做的事情应该有效 - 但事实并非如此。因此,我误解了一些基本的东西......

【问题讨论】:

  • “我以为fork()把父进程的整个地址空间都做了一个拷贝,好像里面会包含各种栈指针……” 这个与问题无关,但至少在大多数现代 UNIX 系统上,fork 在调用时不会复制整个地址空间。它使用 copy-on-write 方案;内存页一旦改变就会被复制。它感觉就像fork时复制的内存页。

标签: c pointers segmentation-fault fork


【解决方案1】:

您正在执行错误的指针操作,并且在第一次调用时很幸运 - 代码应该如下所示:

load_data(char **data);

char* data = NULL;
load_data(&data);
printf("String 0: %s\n", data);
fork(); 
printf("String 0 again: %s\n", data);    /* Doesn't Segfault Here! */

【讨论】:

  • 顺便说一句,应该是NULL全部大写。
  • 这是假设 OP 的函数在 C++ 中是 load_data(char *&)。可能是这样,并且 OP 的用法肯定是错误的,但是 OP 有可能需要 char **
  • 我确实需要 char**,因为我正在处理一些现有代码,并且 load_data 函数已经为我编写了 char**。在我的实际用例中,数据实际上是一个 argv**,我将把 argv[0] 传递给一个 execve 调用。在这种情况下,有什么技巧可以让这项工作发挥作用吗?
【解决方案2】:

在您的情况下,data 没有指向任何地方。 使用未初始化的变量是未定义的行为。即使它在 load_data 函数内部发生了变化,变化也不会在外部可见。

您需要使data 指向有效的东西,或者将data 的地址传递给函数以使更改“返回”,如load_data(char ***data)


您的代码只需稍加改动即可使其成为一个完整的程序,对我“有效”

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int load_data(char **data);

int main(void) {
  char **data;
  data = malloc(2 * sizeof *data);
  assert(data && "no memory");
  load_data(data);
  printf("String 0: %s\n", data[0]);
  fork();
  printf("String 0 again: %s\n", data[0]);
  return 0;
}

int load_data(char **data) {
  data[0] = "one";
  data[1] = "two";
  return 2;
}

还有一个示例运行

$ ./a.out 字符串 0:一个 再次字符串 0:一 再次字符串 0:一

【讨论】:

  • 您的代码在我的系统上也可以正常工作,但在这种情况下我不能使用动态内存。我不确定我的实际代码和你的代码有什么不同,除此之外......这也是我如此困惑的部分原因。
  • 您的data 未初始化。在我的答案顶部查看我的新 cmets。
猜你喜欢
  • 2014-12-19
  • 2021-04-30
  • 2016-04-14
  • 1970-01-01
  • 2021-10-20
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多