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, w开发者_高级运维hich 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)
You should think about writing a function, let's call it step_once()
, which will take input
with n
numbers, and write to the corresponding output
with m = n/2
elements. n
above is the number of input numbers + 1, with the last element of input
equal to 0.
In your driver function, let's say main()
: if output
contains 1 number, you are done. Otherwise, you reallocate input
to contain n_new = m+1
elements, reallocate output
to contain m_new = n_new/2
elements, and call the function step_once()
again. You keep doing this until you get one number:
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
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]- 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 newinput
.- set
input
= [3 7 11 7 0] n
= len(input
) = 5m
=n/2
= 2output
= [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 newinput
.- set
input
= [10 18 0] n
= len(input
) = 3m
=n/2
= 1output
= [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.
Try this, if you want to change the pointers.
void ChangePointers(int **input, int **output)
and
ChangePointers(&input, &output);
You have a couple of off-by-one errors:
for(i = 0; i < argc; i++)
while(calc > 0)
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 want
valgrind --trace-children=yes ./coordinator 1 2 3 4
EDIT: 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 calling realloc
but not on a pointer you got back from malloc
. Maybe you've done some pointer arithmetic?
Can't say more without seeing the code, but I hope you find valgrind helpful.
精彩评论