gpt4 book ai didi

c - 使用 fork() 计算接收到的命令行参数的总和时出现问题

转载 作者:太空狗 更新时间:2023-10-29 15:41:28 25 4
gpt4 key购买 nike

我正在尝试根据从命令行收到的数字集来计算总和,并且我使用一个名为 worker 的配套程序来为我计算。如果收到的数字数量是奇数,它会在数字数量上加一个零,使集合成为偶数。

这是一个易于理解的程序流程(归功于 Alok):

举个例子会更清楚:

假设您要添加 7 个数字:1 2 3 4 5 6 7

./协调员 1 2 3 4 5 6 7

  1. 输入 = [1 2 3 4 5 6 7 0]
  2. n = len(输入) = 8
  3. m = n/2 = 4
  4. 输出 = [0 0 0 0]
  5. 我们 fork 4 个进程,第一个进程获得 [1 2],第二个进程获得 [3 4],...
  6. 4个进程分别返回3、7、11、7,我们分配给output。
  7. 输出有 4 个元素,所以我们为新输入分配 4+1 = 5 个元素的空间。
  8. 设置输入 = [3 7 11 7 0]
  9. n = len(输入) = 5
  10. m = n/2 = 2
  11. 输出= [0 0]
  12. 我们 fork 2 个进程,第一个得到 [3 7],第二个得到 [11 7]
  13. 这 2 个进程返回 10、18,我们将其分配给输出。
  14. 输出有 2 个元素,所以我们为新输入分配 2+1 = 3 个元素的空间。
  15. 设置输入 = [10 18 0]
  16. n = len(输入) = 3
  17. m = n/2 = 1
  18. 输出= [0]
  19. 我们 fork 一个进程,它得到 [10 18]
  20. 该过程返回 28,我们将其分配给输出。
  21. 输出有 1 个元素,所以我们完成了。

虽然在这组特定的数字上我得到:

Process ID: 15195 
Sum of 1 and 2 is 3

Process ID: 15196
Sum of 3 and 4 is 7

Process ID: 15197
Sum of 5 and 6 is 11

Process ID: 15198
Sum of 7 and 0 is 7

*** glibc detected *** ./coordinator: free(): invalid next size (fast): 0x080ec048 ***

后跟堆错误列表。

我相信我没有正确地重新分配指针的大小,我在第一次调用 next_step() 后尝试将旧输出重定向到新输入。所以它试图将数据放入没有空间的内存部分。

更新:

@诺曼

这是我收到的输出:

==3585== Memcheck, a memory error detector
==3585== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3585== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==3585== Command: ./coordinator 1 2 3 4
==3585==
calc: 2:
input[0]: 1
input[1]: 2
input[2]: 3
input[3]: 4
==3585== Use of uninitialised value of size 4
==3585== at 0x4076186: ??? (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x4079A81: vfprintf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x4080F7F: printf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x8048833: main (in /home/bryan/cpp/coordinator)
==3585==
==3585== Conditional jump or move depends on uninitialised value(s)
==3585== at 0x407618E: ??? (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x4079A81: vfprintf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x4080F7F: printf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x8048833: main (in /home/bryan/cpp/coordinator)
==3585==
==3585== Conditional jump or move depends on uninitialised value(s)
==3585== at 0x4077877: vfprintf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x4080F7F: printf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x8048833: main (in /home/bryan/cpp/coordinator)
==3585==
==3585== Conditional jump or move depends on uninitialised value(s)
==3585== at 0x407789B: vfprintf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x4080F7F: printf (in /lib/tls/i686/cmov/libc-2.10.1.so)
==3585== by 0x8048833: main (in /home/bryan/cpp/coordinator)
==3585==
input[4]: 0
==3586== Memcheck, a memory error detector
==3586== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3586== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==3586== Command: ./worker 1 2
==3586==
Process ID: 3586
Sum of 1 and 2 is 3

==3586==
==3586== HEAP SUMMARY:
==3586== in use at exit: 0 bytes in 0 blocks
==3586== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3586==
==3586== All heap blocks were freed -- no leaks are possible
==3586==
==3586== For counts of detected and suppressed errors, rerun with: -v
==3586== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
==3587== Memcheck, a memory error detector
==3587== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3587== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==3587== Command: ./worker 3 4
==3587==
Process ID: 3587
Sum of 3 and 4 is 7

==3587==
==3587== HEAP SUMMARY:
==3587== in use at exit: 0 bytes in 0 blocks
==3587== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3587==
==3587== All heap blocks were freed -- no leaks are possible
==3587==
==3587== For counts of detected and suppressed errors, rerun with: -v
==3587== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
==3585== Invalid write of size 4
==3585== at 0x8048A3A: main (in /home/bryan/cpp/coordinator)
==3585== Address 0x417f0b4 is 8 bytes after a block of size 4 alloc'd
==3585== at 0x4024C6C: malloc (vg_replace_malloc.c:195)
==3585== by 0x4024CF6: realloc (vg_replace_malloc.c:476)
==3585== by 0x8048A25: main (in /home/bryan/cpp/coordinator)
==3585==
==3588== Memcheck, a memory error detector
==3588== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3588== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==3588== Command: ./worker 3 7
==3588==
Process ID: 3588
Sum of 3 and 7 is 10

==3588==
==3588== HEAP SUMMARY:
==3588== in use at exit: 0 bytes in 0 blocks
==3588== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3588==
==3588== All heap blocks were freed -- no leaks are possible
==3588==
==3588== For counts of detected and suppressed errors, rerun with: -v
==3588== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)
==3585== Invalid read of size 4
==3585== at 0x8048AB5: main (in /home/bryan/cpp/coordinator)
==3585== Address 0x417f0e0 is 0 bytes after a block of size 0 alloc'd
==3585== at 0x4024C6C: malloc (vg_replace_malloc.c:195)
==3585== by 0x4024CF6: realloc (vg_replace_malloc.c:476)
==3585== by 0x8048A77: main (in /home/bryan/cpp/coordinator)
==3585==
The final sum is: 0==3585==
==3585== HEAP SUMMARY:
==3585== in use at exit: 28 bytes in 2 blocks
==3585== total heap usage: 4 allocs, 2 frees, 32 bytes allocated
==3585==
==3585== LEAK SUMMARY:
==3585== definitely lost: 8 bytes in 1 blocks
==3585== indirectly lost: 0 bytes in 0 blocks
==3585== possibly lost: 20 bytes in 1 blocks
==3585== still reachable: 0 bytes in 0 blocks
==3585== suppressed: 0 bytes in 0 blocks
==3585== Rerun with --leak-check=full to see details of leaked memory
==3585==
==3585== For counts of detected and suppressed errors, rerun with: -v
==3585== Use --track-origins=yes to see where uninitialised values come from
==3585== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 11 from 6)

最佳答案

你应该考虑编写一个函数,我们称它为step_once(),它将采用inputn 个数字,并写入到相应的 outputm = n/2 元素。上面的n是输入数字的个数+1,input的最后一个元素等于0。

在您的驱动程序函数中,假设main():如果output 包含1 个数字,您就完成了。否则,您重新分配 input 以包含 n_new = m+1 元素,重新分配 output 以包含 m_new = n_new/2 元素,并再次调用函数 step_once()。你一直这样做,直到你得到一个数字:

function next_step(input, output, n, m):
n := number of input numbers # this is 1 greater than
# the number of numbers being summed
m := n / 2 # C division
n_children := m
i := 0
while i < m:
fork worker with input[2*i] and input[2*i+1]
get result in output[i]
i := i + 1

function main:
set n := length(input) + 1
set m := n/2
allocate memory for input # n+1 elements, last = 0
allocate memory for output # m elements
set values in input
while True:
next_step(input, output, n, m)
if length or output == 1:
done, return
else:
set n := length(output) + 1
set m := n/2
allocate space for new_input # n elements
set new_input := output + [0]
free input and output
set input := new_input
allocate memory for output # m elements

优点是您可以测试您的 next_step() 函数以确保其正常工作,从而使调试更容易。

举个例子会更清楚:

假设您要添加 7 个数字:1 2 3 4 5 6 7

  1. 输入 = [1 2 3 4 5 6 7 0]
  2. n = len(input) = 8
  3. m = n/2 = 4
  4. 输出 = [0 0 0 0]
  5. 我们 fork 4 个进程,第一个进程获得 [1 2],第二个进程获得 [3 4],...
  6. 4个进程分别返回3、7、11、7,我们分配给output
  7. output 有 4 个元素,因此我们为新的 input 分配 4+1 = 5 个元素的空间。
  8. 设置输入 = [3 7 11 7 0]
  9. n = len(input) = 5
  10. m = n/2 = 2
  11. 输出 = [0 0]
  12. 我们 fork 2 个进程,第一个得到 [3 7],第二个得到 [11 7]
  13. 这 2 个进程返回 10、18,我们将其分配给 output
  14. output 有 2 个元素,因此我们为新的 input 分配 2+1 = 3 个元素的空间。
  15. 设置输入 = [10 18 0]
  16. n = len(input) = 3
  17. m = n/2 = 1
  18. 输出 = [0]
  19. 我们 fork 一个进程,它得到 [10 18]
  20. 该过程返回 28,我们将其分配给 output
  21. 输出有 1 个元素,所以我们完成了。

关于c - 使用 fork() 计算接收到的命令行参数的总和时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2214604/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com