【问题标题】:C sprintf causing a segmentation faultC sprintf 导致分段错误
【发布时间】:2010-03-04 18:50:35
【问题描述】:

我正在尝试将参数传递给父文件,该文件应该为每对参数创建一个子进程。子进程将把每一对相加并将它们的总和返回给父进程。如果传入的参数数量为奇数,我会在 argv 数组的末尾添加一个 0 以使其均匀。这种情况一直在发生,直到所有参数都加起来,最后打印出它们的总和。

除了我传入偶数个参数时,一切正常。子进程将成功添加前两个参数并返回它们,但是当父进程执行 sprintf 时(第 58 行)总是有一个 segmentation fault。

这是父进程和子进程的代码(我使用的是 pastebin,所以这里看起来不是很混乱。它们将在一天后过期,所以如果需要我可以重新发布它们):

第二个文件在编译时必须调用worker 才能被第一个文件运行。我在Ubuntu 9.10上使用gcc

以下是一些关于如何运行程序的示例:

gcc -o parent parent.c
gcc -o worker worker.c
./parent 1 2 3 4

(上面的示例将以segmentation fault 结尾,就像我在上面解释的那样)。答案应该是10,因为(1 + 2) + (3 + 4) = 10。

虽然传入奇数个参数,但下面的这个可以正常工作:

./parent 1 2 3

这个问题的答案应该是6。

任何帮助将不胜感激!

【问题讨论】:

  • 你有一个错误。该错误不在sprintf 中。
  • 这不仅仅是一个错误;这是对事情如何运作的误解。该程序似乎正试图完全按照他的意愿去做——这就是问题所在:-)
  • @Alok:我刚刚使链接可点击(OP 无法做到这一点,因为他只有 1 个代表),所以希望这能让你的生活更轻松。
  • 感谢您的帮助。当我第一次开始制作这个程序时,出于好奇,我尝试将其添加到 artray 中,并且似乎奏效了。这就是为什么我尝试更进一步,但我现在意识到我不应该修改 argv 和 argc

标签: c process segmentation-fault parent printf


【解决方案1】:

覆盖参数列表充其量是一个严重的变态,最坏的情况是一个保证的错误。这就是您在 sprintf 调用中所做的 - 您传递的第一个参数是传递给 main() 的字符串之一。你为什么要这么做?

[编辑] 我看到您甚至对此发表了评论。好吧,我不知道当你这样做时你认为应该发生什么;如果你解释你的想法,那么有人可能会解释你在哪里感到困惑。您不能将新内容添加到“argv”数组中。这没有道理。这是系统在启动进程时分配的内容,您基本上应该将其视为只读的(除非您真的知道自己在做什么)。

【讨论】:

  • 感谢您的回复。那么我应该将所有新总和复制到一个单独的整数数组中吗?我想我可以通过在末尾添加所有新总和并递增 argc 来保持我的 for 循环运行
  • 可能是国产的setproctitle! :-P
  • @Dave 当您将字符串添加到参数列表时,您期望会发生什么?换句话说,目标是什么?是什么让你认为这是个好主意? (不是在取笑你;我正在努力弄清楚你想要完成的事情。)
  • 我想通过将所有新总和添加到 argv 数组来保持循环。换句话说,我认为这很简单,因为我不必将从子进程返回的整数转换为字符串,然后将它们添加到新的 char 数组中。
【解决方案2】:

C 标准允许修改argv 指向的字符串:

参数argc和argv以及argv数组所指向的字符串应该可以被程序修改,并在程序启动和程序终止之间保留它们最后存储的值。

但它不能保证您在argv 中写入超过可用的参数数量,这是您在argv 末尾存储总和时所做的。

您似乎将argv[i] 用于char * 变量。为什么不为了存储总和而声明单独的变量呢?如果要求和的数字的数量是奇数,您也不需要将 "0" 存储在 argv[argc-1] 中 - 您可以在循环中轻松确定,并将 "0" 传递给最后一个工作人员。

【讨论】:

  • 谢谢,这很有意义!
【解决方案3】:
        argc++;
        sprintf(argv[argc-1],"%d",tmp);

你正在离开这里的数组边界。顺便说一句,写入 argv 有什么用?

【讨论】:

  • 你好,你写的代码就是我用来向 argv 数组添加值的代码。
  • C 的美妙之处在于它只是内存。 argv 数组不像 PHP 或 javascript 中的数组,您可以在其中动态添加项目并且它可以理解。 [] 运算符所做的只是访问给定偏移量的一块内存。由于数组的大小是固定的,因此您正试图访问其控制之外的一块内存。这可能会导致任何数量的奇怪行为(从段错误到奇怪的 heisenbugs)。简而言之,不要这样做! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多