אני מקמפל עם libmap המעודכן של csl3, עם הפקודה הבאה:
gcc -std=c99 -o election -Wall -pedantic-errors -Werror -DNDEBUG *.c tests/electionTests*.c -L. -lmap -g
במהלך בדיקה של התוכנית ב valgrind עולות השגיאות הבאות:
==22800== Invalid read of size 8
==22800== at 0x404EA3: mapGetNext (map.c:251)
==22800== by 0x401676: electionRemoveAreas (election.c:495)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520d980 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x401657: electionRemoveAreas (election.c:497)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012D3: electionAddArea (election.c:385)
==22800== by 0x403B1E: testElectionRemoveAreas (electionTestsExample.c:316)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
==22800== Invalid read of size 8
==22800== at 0x404EBB: mapGetNext (map.c:252)
==22800== by 0x401676: electionRemoveAreas (election.c:495)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520d980 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x401657: electionRemoveAreas (election.c:497)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012D3: electionAddArea (election.c:385)
==22800== by 0x403B1E: testElectionRemoveAreas (electionTestsExample.c:316)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
==22800== Invalid read of size 8
==22800== at 0x404EA3: mapGetNext (map.c:251)
==22800== by 0x4016E4: electionRemoveAreas (election.c:503)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520d880 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x4016C8: electionRemoveAreas (election.c:505)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012A7: electionAddArea (election.c:379)
==22800== by 0x403B1E: testElectionRemoveAreas (electionTestsExample.c:316)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
==22800== Invalid read of size 8
==22800== at 0x404EBB: mapGetNext (map.c:252)
==22800== by 0x4016E4: electionRemoveAreas (election.c:503)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520d880 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x4016C8: electionRemoveAreas (election.c:505)
==22800== by 0x403B9C: testElectionRemoveAreas (electionTestsExample.c:319)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012A7: electionAddArea (election.c:379)
==22800== by 0x403B1E: testElectionRemoveAreas (electionTestsExample.c:316)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
Running testElectionRemoveAreas ... [OK]
==22800== Invalid read of size 8
==22800== at 0x404EA3: mapGetNext (map.c:251)
==22800== by 0x401676: electionRemoveAreas (election.c:495)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520e040 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x401657: electionRemoveAreas (election.c:497)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012D3: electionAddArea (election.c:385)
==22800== by 0x403C05: testElectionRemoveAreasTribeExist (electionTestsExample.c:326)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
==22800== Invalid read of size 8
==22800== at 0x404EBB: mapGetNext (map.c:252)
==22800== by 0x401676: electionRemoveAreas (election.c:495)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520e040 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x401657: electionRemoveAreas (election.c:497)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012D3: electionAddArea (election.c:385)
==22800== by 0x403C05: testElectionRemoveAreasTribeExist (electionTestsExample.c:326)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
==22800== Invalid read of size 8
==22800== at 0x404EA3: mapGetNext (map.c:251)
==22800== by 0x4016E4: electionRemoveAreas (election.c:503)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520df40 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x4016C8: electionRemoveAreas (election.c:505)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012A7: electionAddArea (election.c:379)
==22800== by 0x403C05: testElectionRemoveAreasTribeExist (electionTestsExample.c:326)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
==22800== Invalid read of size 8
==22800== at 0x404EBB: mapGetNext (map.c:252)
==22800== by 0x4016E4: electionRemoveAreas (election.c:503)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Address 0x520df40 is 16 bytes inside a block of size 24 free'd
==22800== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==22800== by 0x4048EA: destroyNode (map.c:53)
==22800== by 0x404DED: mapRemove (map.c:229)
==22800== by 0x4016C8: electionRemoveAreas (election.c:505)
==22800== by 0x403D09: testElectionRemoveAreasTribeExist (electionTestsExample.c:331)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800== Block was alloc'd at
==22800== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==22800== by 0x4047BE: createNode (map.c:20)
==22800== by 0x404C54: mapPut (map.c:175)
==22800== by 0x4012A7: electionAddArea (election.c:379)
==22800== by 0x403C05: testElectionRemoveAreasTribeExist (electionTestsExample.c:326)
==22800== by 0x4046A4: main (electionTestsExample.c:509)
==22800==
הקוד שלי ב election.c:495 הוא:
MAP_FOREACH(key, election->votes) {
הקוד שלי ב election.c:497 הוא:
if(mapRemove(election->votes, key) == MAP_ITEM_DOES_NOT_EXIST) {
מה שאני מזהה מדיבוג שעשיתי זה שבלולאת ה MAP_FOREACH האיטרטור (המפתח) נקרא, לאחר מכן מתבצע שחרור של האלמנט (שכולל כמובן שחרור של הזיכרון שבו שמור המפתח), ואז לאחר השחרור שוב חוזרים לראש הלולאה ושם נעשה ניסיון קריאה נוסף של המפתח, למרות שיש בו עכשיו ערך זבל.
הקריאה האסורה היא ב:
mapGetNext (map.c:252)
שנמצא ב libmap.
כשאני מקמפל את הקוד עם הפקודה הבאה:
gcc -std=c99 -o election -Wall -pedantic-errors -Werror -DNDEBUG tests/electionTests*.c mtm_map/*.c *.c -g
כלומר כשאני משתמש בקבצי המפה שלי ולא ב libmap, לא עולות שגיאות זיכרון.
==32257== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
הטסט שבו עולה השגיאה בפעם הראשונה:
bool testElectionRemoveAreas() {
Election election = electionCreate();
ASSERT_TEST(electionAddArea(election, 1, "first area") == ELECTION_SUCCESS);
ASSERT_TEST(electionAddArea(election, 2, "second area") == ELECTION_SUCCESS);
ASSERT_TEST(electionRemoveAreas(election, deleteOnlyFirstArea) == ELECTION_SUCCESS);
electionDestroy(election);
return true;
}
השגיאה חוזרת על עצמה שוב ושוב בכל טסט שמשתמש ב electionRemoveAreas.
אני אציין אבל שזה לא קורה בכל MAP_FOREACH, למשל זה כן קורה בקטע קוד הזה:
MAP_FOREACH(key, election->areas) {
if(should_delete_area(stringToInt(key))) {
if(mapRemove(election->areas, key) == MAP_ITEM_DOES_NOT_EXIST) {
return ELECTION_AREA_NOT_EXIST;
}
}
}
אבל לא קורה בקטע קוד הזה:
MAP_FOREACH(key, election->votes) {
ElectionResult remove_tribe_return = ......some_function.......;
if(remove_tribe_return != ELECTION_SUCCESS) {
free(tribe_id_str);
return remove_tribe_return;
}
}