A: 

Try this, if you want to change the pointers.

void ChangePointers(int **input, int **output)

and

ChangePointers(&input, &output);

Aman Jain
I made the necessary changes, but I am still getting fault errors.
A: 

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.

Norman Ramsey
A: 

@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)
A: 

You have a couple of off-by-one errors:

  1. for(i = 0; i < argc; i++)
  2. while(calc > 0)
Greg Bacon
+1  A: 

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

  1. input = [1 2 3 4 5 6 7 0]
  2. n = len(input) = 8
  3. m = n/2 = 4
  4. output = [0 0 0 0]
  5. We fork 4 process, first process gets [1 2], second gets [3 4], ...
  6. The 4 processes return 3, 7, 11, 7 respectively, which we assign to output.
  7. output has 4 elements, so we allocate space for 4+1 = 5 elements for the new input.
  8. set input = [3 7 11 7 0]
  9. n = len(input) = 5
  10. m = n/2 = 2
  11. output = [0 0]
  12. We fork 2 processes, first gets [3 7], second gets [11 7]
  13. The 2 processes return 10, 18, which we assign to output.
  14. output has 2 elements, so we allocate space for 2+1 = 3 elements for the new input.
  15. set input = [10 18 0]
  16. n = len(input) = 3
  17. m = n/2 = 1
  18. output = [0]
  19. We fork one process, which gets [10 18]
  20. The process returns 28, which we assign to output.
  21. output has 1 element, so we are done.
Alok
This line: set input := output + [0]Does that mean populate input with outputs data or redirect the pointers? But if you free the memory right before that, won't I lose the arguments stored in output?
@ray2k, good point. Fixed. You don't really need to copy data over from `output` to `input`, you can just set the `input` pointer to point to `output`, but then you have to be more careful about the number of elements to sum. That is also not too hard, but I wanted to avoid mentioning that. Once you get this working, you can think about further optimization.
Alok
@Alok, Hello I fixed my code as per the pseudocode that you gave me but it is giving me segmentation fault errors out the wazoo. I updated my original post with this. Could you give me any feedback on my new code? Thank you.
Your main trouble seems to be `*input = *new_input` line: you want to copy the elements in a loop, something like: `for(i=0; i < m; ++i) new_input[i] = input[i];`, followed by `free(input);` and `input = new_input;`. I haven't looked at other parts of the code in detail yet. Good luck!
Alok
I've worked on my program over night and I'm still stuck at the reallocation part after the first call to next_step(). I'm afraid I won't finish this. I took the advice of others on here from a previous post and I'm doing it the right way, but still receiving new heap errors. I updated my original post to make clear of this new problem.
@ray2k: the first thing you need to do is start from scratch. You should eliminate most of your variables, such as `length`, `calc`, etc. Keep things simple.
Alok