Discussion:
Hmm...a6q3, no memory leak but...
(too old to reply)
Ke
2010-02-19 09:30:38 UTC
Permalink
My code passed this testing UI:

int main() {
ilist x = icons_destroy(2, icons_destroy(3, iempty()));
ilist y = icons_destroy(20, icons_destroy(30, icons_destroy(40,
iempty())));
ilist z = icons_destroy(100, iempty());
ilist q = iappend_destroy(x, iappend_destroy(y,
iappend_destroy(icopy(x), iappend_destroy(z, iempty()))));

while(iempty_huh(q) == 0) {
printf("%d ", ifirst(q));
q = irest_destroy(q);
}
//idelete(q);
return 0;
}

My irest_destroy frees the first element in the input ilist and produce
a pointer that points to the rest of it, so after that test printing
loop the ilist q will be completely freed; if not printing then that
idelete(q) must be enabled. My iappend kills il1 and il2 when it's done
its job, so yeah. Everything is looking pretty tight.

But Marmoset told me otherwise:

Running p3a.c -- input from p3a.in.1 -- output to p3a.out.1
= Invalid read of size 4
= at 0x804920B: idelete (ilist_destructive.c:98)
= by 0x80492C5: iappend_destroy (ilist_destructive.c:127)
= by 0x804944B: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804916E: irest_destroy (ilist_destructive.c:61)
Program finished with errors -- see p3a.err.1
= Invalid read of size 4
= at 0x804920B: idelete (ilist_destructive.c:98)
= by 0x80492C5: iappend_destroy (ilist_destructive.c:127)
= by 0x804944B: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804916E: irest_destroy (ilist_destructive.c:61)
= by 0x8049271: iappend_destroy (ilist_destructive.c:117)
= by 0x804944B: main (p3a.c:31)
= Invalid free() / delete / delete[]
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804921A: idelete (ilist_destructive.c:99)
= by 0x80492C5: iappend_destroy (ilist_destructive.c:127)
= by 0x804944B: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804916E: irest_destroy (ilist_destructive.c:61)
= by 0x8049271: iappend_destroy (ilist_destructive.c:117)
= by 0x804944B: main (p3a.c:31)
= ERROR SUMMARY: 2000 errors from 2 contexts (suppressed: 12 from 1)
= malloc/free: in use at exit: 0 bytes in 0 blocks.
Try again.

Is it telling me some free() calls have landed in the wrong places? I'm
sure "malloc/free: in use at exit: 0 bytes in 0 blocks." has indicated
that I've got no memory leak, but what now?

Thanks!
Gordon V. Cormack
2010-02-19 13:49:29 UTC
Permalink
You need much more extensive testing than this.

Try all combinations of lists of length 0,1,2,3.

Try the results of all ilist operations: iempty,
icons_delete, irest_delete, icopy, iappend_delete,
and all combinations of them.

Write code to verify that your output is corrrect.
Post by Ke
int main() {
ilist x = icons_destroy(2, icons_destroy(3, iempty()));
ilist y = icons_destroy(20, icons_destroy(30, icons_destroy(40,
iempty())));
ilist z = icons_destroy(100, iempty());
ilist q = iappend_destroy(x, iappend_destroy(y,
iappend_destroy(icopy(x), iappend_destroy(z, iempty()))));
while(iempty_huh(q) == 0) {
printf("%d ", ifirst(q));
q = irest_destroy(q);
}
//idelete(q);
return 0;
}
Ke
2010-02-19 17:42:15 UTC
Permalink
Post by Gordon V. Cormack
You need much more extensive testing than this.
Try all combinations of lists of length 0,1,2,3.
Try the results of all ilist operations: iempty,
icons_delete, irest_delete, icopy, iappend_delete,
and all combinations of them.
Write code to verify that your output is corrrect.
Post by Ke
int main() {
ilist x = icons_destroy(2, icons_destroy(3, iempty()));
ilist y = icons_destroy(20, icons_destroy(30, icons_destroy(40,
iempty())));
ilist z = icons_destroy(100, iempty());
ilist q = iappend_destroy(x, iappend_destroy(y,
iappend_destroy(icopy(x), iappend_destroy(z, iempty()))));
while(iempty_huh(q) == 0) {
printf("%d ", ifirst(q));
q = irest_destroy(q);
}
//idelete(q);
return 0;
}
I've scrambled them all together like this but I still got no errors at
all...Aww man, talk about frustration now. DX

int main() {
ilist x = icons_destroy(2, icons_destroy(3, iempty()));
ilist y = icons_destroy(20, icons_destroy(30, icons_destroy(40,
iempty())));
ilist z = icons_destroy(100, iempty());
//ilist q = iappend_destroy(x, iappend_destroy(y,
iappend_destroy(icopy(x), iappend_destroy(z, iempty()))));
ilist q = icons_destroy(111, irest_destroy(icons_destroy(222,
icons_destroy(333, icons_destroy(444, iappend_destroy(x,
iappend_destroy(y, iappend_destroy(z, iappend_destroy(icopy(x),
iempty())))))))));
ilist p = irest_destroy(icons_destroy(100, icons_destroy(200,
iempty())));
ilist r = iempty();
ilist s = icopy(p);
ilist t = irest_destroy(s);
//while(iempty_huh(q) == 0) {
// printf("%d ", ifirst(q));
// q = irest_destroy(q);
//}
idelete(q);
idelete(p);
idelete(t);
idelete(r); //doesn't matter at all since idelete detects iempty()
return 0;
}
Gordon V. Cormack
2010-02-19 17:54:32 UTC
Permalink
Use all combinations of lists of length 0,1,2,3,
and include code to check that your results
are correct.

I don't see, for example, a test for

iappend(iempty(),iempty())

You should try to test a representative of every
possible situation, not just cases where you think
your error lies. Such situations often occur when
you use examples close to the smallest and largest
possible sizes.

For this assignment, the smallest possible size
is 0, and testing 1,2,3 helps to insure that you
don't just pass the special cases of 0 and 1.
The largest possible size is open-ended; try a few
thousand elements. That will help ensure that

(a) your running time is reasonable
(b) you haven't just patched your implementation
to handle 0,1,2,3 in an ad hoc manner
[I have seen a distressing number of submissions
that handle 0 and 1 as special cases, and then
when they don't work, are modified to handle 2
as yet another special case.]

If your tests succeed and the Marmoset ones fail,
you have not done a good enough job of covering
every possible situation. Or, perhaps, verifying
that the result is correct.

I trust you have downloaded and installed Runc v0.3,
as described in the assignment specification.
Ke
2010-02-20 05:01:51 UTC
Permalink
Post by Gordon V. Cormack
Use all combinations of lists of length 0,1,2,3,
and include code to check that your results
are correct.
I don't see, for example, a test for
iappend(iempty(),iempty())
You should try to test a representative of every
possible situation, not just cases where you think
your error lies. Such situations often occur when
you use examples close to the smallest and largest
possible sizes.
For this assignment, the smallest possible size
is 0, and testing 1,2,3 helps to insure that you
don't just pass the special cases of 0 and 1.
The largest possible size is open-ended; try a few
thousand elements. That will help ensure that
(a) your running time is reasonable
(b) you haven't just patched your implementation
to handle 0,1,2,3 in an ad hoc manner
[I have seen a distressing number of submissions
that handle 0 and 1 as special cases, and then
when they don't work, are modified to handle 2
as yet another special case.]
If your tests succeed and the Marmoset ones fail,
you have not done a good enough job of covering
every possible situation. Or, perhaps, verifying
that the result is correct.
I trust you have downloaded and installed Runc v0.3,
as described in the assignment specification.
My reaction of Marmoset testing result as of now:
http://tinyurl.com/yhzdvpc

Man...can't believe I'm getting stuck on this thing for so long.

I've gotten around all possible base cases and the short length mash-ups
I could think of (yes, multiple empty icons, iappend, irest, ifirst,
idelete, etc, as well as a messy mixture of ilists of different lengths,
calling those functions on NULL ilists, and so on). The error remains
the same on Marmoset. I use the "0 special case" method so I'm not using
any funny looking base cases here. Just like before, I'm getting pretty
much the same kind of error message:

Running p3a.c -- input from p3a.in.1 -- output to p3a.out.1
= Invalid read of size 4
= at 0x8049196: irest_destroy (ilist_destructive.c:65)
= by 0x804926A: idelete (ilist_destructive.c:107)
= by 0x8049312: iappend_destroy (ilist_destructive.c:134)
= by 0x8049497: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x80491A5: irest_destroy (ilist_destructive.c:66)
= by 0x80492BE: iappend_destroy (ilist_destructive.c:124)
= by 0x8049497: main (p3a.c:31)
= Invalid free() / delete / delete[]
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x80491A5: irest_destroy (ilist_destructive.c:66)
= by 0x804926A: idelete (ilist_destructive.c:107)
= by 0x8049312: iappend_destroy (ilist_destructive.c:134)
= by 0x8049497: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x80491A5: irest_destroy (ilist_destructive.c:66)
= by 0x80492BE: iappend_destroy (ilist_destructive.c:124)
= by 0x8049497: main (p3a.c:31)
Program finished with errors -- see p3a.err.1
= Invalid read of size 4
= at 0x8049196: irest_destroy (ilist_destructive.c:65)
= by 0x804926A: idelete (ilist_destructive.c:107)
= by 0x8049312: iappend_destroy (ilist_destructive.c:134)
= by 0x8049497: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
Try again.

Here I tried a different method with idelete, which also worked but
ended up being buggy.

I'm sure that testing giant ilists will not make any difference (since
by some simple inductive checks, they will work, until it hits the same
bugged free() call near end).

Clearly I must have overlooked *something* regarding the base cases, but
omg...tips? I've made a detailed debugging process that printf out each
malloc, free, and blocks of variable declaration etc, printed the result
on paper, checked them by hand one by one, and couldn't find any fault...

Thanks again!
Gordon V. Cormack
2010-02-20 05:20:46 UTC
Permalink
Did you try:

append(x,x)
Ke
2010-02-20 21:41:12 UTC
Permalink
Post by Gordon V. Cormack
append(x,x)
My face looks funny now...

Thank you, thank you!

Ke
2010-02-19 17:51:24 UTC
Permalink
Post by Gordon V. Cormack
You need much more extensive testing than this.
Try all combinations of lists of length 0,1,2,3.
Try the results of all ilist operations: iempty,
icons_delete, irest_delete, icopy, iappend_delete,
and all combinations of them.
Write code to verify that your output is corrrect.
Post by Ke
int main() {
ilist x = icons_destroy(2, icons_destroy(3, iempty()));
ilist y = icons_destroy(20, icons_destroy(30, icons_destroy(40,
iempty())));
ilist z = icons_destroy(100, iempty());
ilist q = iappend_destroy(x, iappend_destroy(y,
iappend_destroy(icopy(x), iappend_destroy(z, iempty()))));
while(iempty_huh(q) == 0) {
printf("%d ", ifirst(q));
q = irest_destroy(q);
}
//idelete(q);
return 0;
}
PS. I printf tested the returned ilists too, and they all turned out to
be correct.
Adrian Duong
2010-02-19 18:44:37 UTC
Permalink
Post by Ke
Running p3a.c -- input from p3a.in.1 -- output to p3a.out.1
= Invalid read of size 4
= at 0x804920B: idelete (ilist_destructive.c:98)
= by 0x80492C5: iappend_destroy (ilist_destructive.c:127)
= by 0x804944B: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804916E: irest_destroy (ilist_destructive.c:61)
Program finished with errors -- see p3a.err.1
= Invalid read of size 4
= at 0x804920B: idelete (ilist_destructive.c:98)
= by 0x80492C5: iappend_destroy (ilist_destructive.c:127)
= by 0x804944B: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804916E: irest_destroy (ilist_destructive.c:61)
= by 0x8049271: iappend_destroy (ilist_destructive.c:117)
= by 0x804944B: main (p3a.c:31)
= Invalid free() / delete / delete[]
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804921A: idelete (ilist_destructive.c:99)
= by 0x80492C5: iappend_destroy (ilist_destructive.c:127)
= by 0x804944B: main (p3a.c:31)
= Address 0x70763e8 is 0 bytes inside a block of size 12 free'd
= at 0x47ED65C: free (vg_replace_malloc.c:323)
= by 0x804916E: irest_destroy (ilist_destructive.c:61)
= by 0x8049271: iappend_destroy (ilist_destructive.c:117)
= by 0x804944B: main (p3a.c:31)
= ERROR SUMMARY: 2000 errors from 2 contexts (suppressed: 12 from 1)
= malloc/free: in use at exit: 0 bytes in 0 blocks.
Try again.
Is it telling me some free() calls have landed in the wrong places? I'm sure
"malloc/free: in use at exit: 0 bytes in 0 blocks." has indicated that I've
got no memory leak, but what now?
Thanks!
Yes, you have no memory leaks. However, you call free too many times.
What's more relevant is your iappend_destroy is attempting to idelete
something that has already been freed. Think about the possible things you
could be trying to call idelete on at line 127.
Loading...