使用 fork() 计算接收到的命令行参数的总和时出现问题
我正在尝试根据从命令行接收到的一组数字来计算总和,并且我使用一个名为worker的配套程序来为我进行计算。如果收到的数字数量是奇数,它将在数字数量上添加零以使该集合成为偶数。
这是程序的流程,以一种可以理解的方式(归功于 Alok):
一个例子会让这一点更清楚:
假设您想要添加 7 个数字: 1 2 3 4 5 6 7
./coordinator 1 2 3 4 5 6 7
- 输入 = [1 2 3 4 5 6 7 0]
- n = len(input) = 8
- m = n/2 = 4
- 输出 = [0 0 0 0]
- 我们分叉 4 个进程,第一个进程获取 [1 2],第二个进程获取[3 4], ...
- 4 个进程分别返回 3, 7, 11, 7,我们将其分配给输出。
- 输出有 4 个元素,因此我们为新输入分配 4+1 = 5 个元素的空间。
- 设置输入 = [3 7 11 7 0]
- n = len(input) = 5
- m = n/2 = 2
- 输出 = [0 0]
- 7]
- 我们分叉 2 个进程,第一个获取 [3 7],第二个获取 [ 11 2 个进程返回 10、18,我们将其分配给输出。
- 输出有 2 个元素,因此我们为新输入分配 2+1 = 3 个元素的空间。
- set input = [10 18 0]
- n = len(input) = 3
- m = n/2 = 1
- output = [0]
- 我们分叉一个进程,它得到 [10 18]
- 该进程返回 28,我们将其分配给输出。
- 输出有 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() 之后我尝试将旧输出重定向到新输入。所以它试图将数据放入内存中没有空间的部分。
更新:
@Norman
这是我收到的输出:
==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)
I'm trying to calculate the sum based off of sets of numbers received from the command line and I use a companion program called worker to due the computation for me. If the amount of numbers received is odd, it will add a zero to the amount of numbers to make the set even.
This is the flow of the program in an understandable way(credit to Alok):
An example will make this clearer:
Let's say you want to add 7 numbers: 1 2 3 4 5 6 7
./coordinator 1 2 3 4 5 6 7
- input = [1 2 3 4 5 6 7 0]
- n = len(input) = 8
- m = n/2 = 4
- output = [0 0 0 0]
- We fork 4 process, first process gets [1 2], second gets [3 4], ...
- The 4 processes return 3, 7, 11, 7 respectively, which we assign to output.
- output has 4 elements, so we allocate space for 4+1 = 5 elements for the new input.
- set input = [3 7 11 7 0]
- n = len(input) = 5
- m = n/2 = 2
- output = [0 0]
- We fork 2 processes, first gets [3 7], second gets [11 7]
- The 2 processes return 10, 18, which we assign to output.
- output has 2 elements, so we allocate space for 2+1 = 3 elements for the new input.
- set input = [10 18 0]
- n = len(input) = 3
- m = n/2 = 1
- output = [0]
- We fork one process, which gets [10 18]
- The process returns 28, which we assign to output.
- output has 1 element, so we are done.
Although on this particular set of numbers I get:
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 ***
Followed by a list of heap errors.
I believe I am not reallocating the size of the pointers correctly in which I attempt to redirect the old output to the new input after the first call to next_step(). So it's trying to put data into a part of memory for which there is no space.
UPDATE:
@Norman
This is the output I receive:
==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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您应该考虑编写一个函数,我们将其称为
step_once()
,它将接受带有n
个数字的input
,并写入相应的 < code>output 与m = n/2
元素。上面的n
是输入数字的数量 + 1,input
的最后一个元素等于 0。在您的驱动程序函数中,假设
main():如果
output
包含 1 个数字,则完成。否则,您将重新分配input
以包含n_new = m+1
元素,重新分配output
以包含m_new = n_new/2
> 元素,并再次调用函数step_once()
。继续执行此操作,直到获得一个数字:优点是您可以测试
next_step()
函数以确保其正常工作,从而使调试更容易。举个例子可以让这一点更清楚:
假设您要添加 7 个数字: 1 2 3 4 5 6 7
input
= [1 2 3 4 5 6 7 0]n
= len(输入
) = 8m
=n/2
= 4输出
= [0 0 0 0]output
。output
有 4 个元素,因此我们为新的input
分配 4+1 = 5 个元素的空间。输入
= [3 7 11 7 0]n
= len(输入
) = 5m
=>n/2
= 2output
= [0 0]输出
。output
有 2 个元素,因此我们为新的input
分配 2+1 = 3 个元素的空间。输入
= [10 18 0]n
= len(输入
) = 3m
=n /2
= 1output
= [0]output
。You should think about writing a function, let's call it
step_once()
, which will takeinput
withn
numbers, and write to the correspondingoutput
withm = n/2
elements.n
above is the number of input numbers + 1, with the last element ofinput
equal to 0.In your driver function, let's say
main()
: ifoutput
contains 1 number, you are done. Otherwise, you reallocateinput
to containn_new = m+1
elements, reallocateoutput
to containm_new = n_new/2
elements, and call the functionstep_once()
again. You keep doing this until you get one number:The advantage is that you can test your
next_step()
function to make sure it works and thus makes debugging easier.An example will make this clearer:
Let's say you want to add 7 numbers: 1 2 3 4 5 6 7
input
= [1 2 3 4 5 6 7 0]n
= len(input
) = 8m
=n/2
= 4output
= [0 0 0 0]output
.output
has 4 elements, so we allocate space for 4+1 = 5 elements for the newinput
.input
= [3 7 11 7 0]n
= len(input
) = 5m
=n/2
= 2output
= [0 0]output
.output
has 2 elements, so we allocate space for 2+1 = 3 elements for the newinput
.input
= [10 18 0]n
= len(input
) = 3m
=n/2
= 1output
= [0]output
.如果您想更改指针,请尝试此操作。
void ChangePointers(int **input, int **output)
和
ChangePointers(&input, &output);
Try this, if you want to change the pointers.
void ChangePointers(int **input, int **output)
and
ChangePointers(&input, &output);
您有几个相差一的错误:
for(i = 0; i < argc; i++)
while(calc > 0)
You have a couple of off-by-one errors:
for(i = 0; i < argc; i++)
while(calc > 0)
Ray,如果不查看有关错误的更多详细信息,很难知道出了什么问题。如果正如我怀疑的那样,这些是运行时错误,您可以在
valgrind
?valgrind
在查明内存错误方面非常有效;在您的应用程序中,您需要编辑:好的,通过 valgrind 错误,我们可以看到 (a) 您向
printf
传递了一些狡猾的东西(如果您使用 < code>-g 你会得到准确的行号),而且你正在调用realloc
但不是在从malloc
返回的指针上调用。也许你已经做过一些指针算术?在没有看到代码的情况下不能说更多,但我希望 valgrind 对您有所帮助。
Ray, it's hard to know what's wrong without seeing more details about the errors. If, as I suspect, these are run-time errors, can you run the code under
valgrind
?valgrind
is extremely effective at pinpointing memory errors; with your application you'll wantEDIT: OK, with the valgrind errors we can see that (a) you're passing something dodgy to
printf
(if you compile with-g
you'll get the exact line number), and also you're callingrealloc
but not on a pointer you got back frommalloc
. Maybe you've done some pointer arithmetic?Can't say more without seeing the code, but I hope you find valgrind helpful.