שאלות תרגיל בית 1

שגיאות זיכרון ב libmap.a

שגיאות זיכרון ב libmap.a

על ידי אליה סוליימנוב בתאריך
מספר תגובות: 5

אני מקמפל עם 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;
}
}

 

בתגובה ל: אליה סוליימנוב

תשובה ל: שגיאות זיכרון ב libmap.a

על ידי אורטל כהן בתאריך
היי,
האם אתה מנסה להריץ פונקציה שאחרי מצב האיטרטור לא מוגדר בעת שימוש בMAP_FOREACH (אני כן רואה שיש מקרים בהם יש לך שגיאה שקשורה לזה)? אם כן אסור לעשות זאת. לדוגמא:
==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)
כתבתי יותר מפורט באחד מהפוסטים שנשאלו בעבר לגבי זה - ממליצה להסתכל.
בתגובה ל: אורטל כהן

תשובה ל: שגיאות זיכרון ב libmap.a

על ידי אליה סוליימנוב בתאריך
תודה אורטל,
זה אכן מה שקרה, ונפתרה התקלה.
העניין לא עלה כשהשתמשתי בקבצים שלי בגלל המימוש שלי לפונקציית mapRemove
בתגובה ל: אליה סוליימנוב

תשובה ל: שגיאות זיכרון ב libmap.a

על ידי בר דבש בתאריך
בתגובה ל: בר דבש

תשובה ל: שגיאות זיכרון ב libmap.a

על ידי אחמד אגבאריה בתאריך
שלום
קיבלתי בדיוק אותה שגיאה אבל לא הבנתי כל כך את ההסבר למעלה.
תוכל להסביר שוב בבקשה?
תודה
בתגובה ל: אחמד אגבאריה

תשובה ל: שגיאות זיכרון ב libmap.a

על ידי בר דבש בתאריך
ישנם פונקציות בmap.h (כתוב בתיעדו שלהן) בהן "לא מובטח שהאיטרטור יהיה במצב תקין אחרי השימוש" - המשמעות הפרקטית היא שאסור להשתמש בהן בתוך לולאת MAP_FOREACH המשתמש באיטרטור. עיין בmap.h תמצא את הפונקציות הללו ותוודא שלא השתמשת בהן בקוד של ELECTION בתוך לולאת MAP_FOREACH.