C 使用fork()计算收到的命令行参数的总和时出现问题
我试图根据从命令行收到的一组数字来计算总和,我使用一个名为worker的配套程序来完成计算。如果收到的数字量为奇数,它将在数字量上加一个零,使集合为偶数 这是一种可以理解的程序流程(归功于Alok): 举个例子可以更清楚地说明这一点: 假设您要添加7个数字:1234567 /协调员1234567C 使用fork()计算收到的命令行参数的总和时出现问题,c,unix,fork,C,Unix,Fork,我试图根据从命令行收到的一组数字来计算总和,我使用一个名为worker的配套程序来完成计算。如果收到的数字量为奇数,它将在数字量上加一个零,使集合为偶数 这是一种可以理解的程序流程(归功于Alok): 举个例子可以更清楚地说明这一点: 假设您要添加7个数字:1234567 /协调员1234567 输入=[12345670] n=len(输入)=8 m=n/2=4 输出=[0] 我们分叉4个进程,第一个进程得到[12],第二个进程得到[34] 这4个进程分别返回3、7、11、7,我们将其分配给输出
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)
如果要更改指针,请尝试此操作 无效更改指针(int**输入,int**输出) 及
变更指针(输入和输出) Ray,如果没有看到错误的更多细节,就很难知道出了什么问题。如果,正如我所怀疑的,这些都是运行时错误,您可以在下面运行代码吗
valgrind
在精确定位内存错误方面非常有效;使用您的应用程序,您将需要
valgrind --trace-children=yes ./coordinator 1 2 3 4
编辑:好的,通过valgrind错误,我们可以看到(a)您正在向printf
传递一些不可靠的东西(如果您使用-g
编译,您将获得准确的行号),并且您正在调用realloc
,但不是在malloc
返回的指针上。也许你做过一些指针运算
如果不看代码,就不能说更多,但我希望valgrind对您有所帮助。您有几个错误:
for(i=0;i
while(计算>0)
您应该考虑编写一个函数,让我们将其称为
step_once()
,它将使用n
数字执行input
,并使用m=n/2
元素写入相应的output
<上面的code>n是输入数字的数目+1,input
的最后一个元素等于0
在驱动程序函数中,假设main()
:如果output
包含1个数字,则完成。否则,您将重新分配input
以包含n_new=m+1
元素,重新分配output
以包含m_new=n_new/2
元素,并再次调用函数step_()。你一直这样做直到你得到一个号码:
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
下一步功能(输入、输出、n、m):
n:=输入数#大于1
#要求和的数字的数目
m:=n/2#C分部
n_儿童:=m
i:=0
而我
优点是,您可以测试next_step()
函数,以确保它工作正常,从而使调试更容易
举个例子可以更清楚地说明这一点:
假设您要添加7个数字:1234567
输入
=[1 2 3 4 5 6 7 0]n
=len(input
)=8m
=n/2
=4输出
=[0]输出
output
有4个元素,因此我们为新的输入分配了4+1=5个元素的空间
输入=[3 7 11 7 0]
n
=len(input
)=5m
=n/2
=2输出
=[0]输出
输出
有2个元素,因此我们为新的输入
分配了2+1=3个元素的空间输入=[10 18 0]
n
=len(input
)=3