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

קריאת מצביע לא מאותחל

קריאת מצביע לא מאותחל

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

שלום,

 

בפרק 3 שקופית 30 אנחנו שמים Initial_Size מצביעי מחרוזת (char*) לא מאותחלים לתוך משתנה elements. לאחר מכן, בשקופית 39 אנחנו מגדירים פונקציית עזר find אשר משתמשת ב strcmp על כל איברי elements. במקרה בו קיים איבר במערך elements אשר עדין לא אותחל, הפונקציה find תבצע קריאה של מצביע לא מאותחל.

האם קריאה כזו תוכל לגרום לשגיאה מסוג - memory: memory leak or out-of-bounds read/write?

האם פרוצדורה זו יכולה להוציא פלט אל הערוץ הסטנדרטי?

בתגובה ל: רון אלפיה

תשובה ל: קריאת מצביע לא מאותחל

על ידי אורטל כהן בתאריך
היי,
לא מצאתי את מה שאתה שואל לגביו בתרגול מספר 3 אז אנסה לענות לפי מה שכתבת.
מכיוון שהמצביע לא מאותחל הוא מכיל ערך זבל, והפונקציה strcmp לא יכולה לבדוק האם ערך הזבל או תקין או לא ולכן עדיין תתבצע.
סביר להניח שתהיה שגיאת זכרון (שניתן למצוא אותה באמצעות הכלי valgrind).
אולם התוכנית עשויה להמשיך לרוץ גם אחרי הקריאה לstrcmp:
נניח במקרה בו ערך הזבל הוא מחרוזת חוקית אבל לא תקינה מבחינת נכונות התוכנית, במקרה זה היא גם תוכל להוציא פלט אל הערוץ הסטנדרטי אבל התוכנית עצמה לא תהיה נכונה.
בתגובה ל: אורטל כהן

תשובה ל: קריאת מצביע לא מאותחל

על ידי רון אלפיה בתאריך
היי,

תודה.
אני התכוונתי לפרק 3 מההרצאות :-)

אני מנסה למצוא שגיאות זיכרון מסוג קריאה של ערך לא מאותחל. עם --leak-check=full אי אפשר למצוא אותם. ניסיתי עם -v ואני מקבל פלט כזה

--9724-- REDIR: 0x4019be0 (ld-linux-x86-64.so.2:index) redirected to 0x58059dab (???)

==9724== Memcheck, a memory error detector
==9724== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9724== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9724== Command: ./map
==9724==
--9724-- Valgrind options:
--9724-- --leak-check=full
--9724-- -v
--9724-- Contents of /proc/version:
--9724-- Linux version 3.10.0-1127.el7.x86_64 (mockbuild@x86-034.build.eng.bos.redhat.com) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Tue Feb 18 16:39:12 EST 2020
--9724--
--9724-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-rdtscp-sse3-avx
--9724-- Page sizes: currently 4096, max supported 4096
--9724-- Valgrind library directory: /usr/lib64/valgrind
--9724-- Reading syms from /home/ronalfia/mtm/ex1_spring/map
--9724-- Reading syms from /usr/lib64/ld-2.17.so
--9724-- Reading syms from /usr/lib64/valgrind/memcheck-amd64-linux
--9724-- object doesn't have a symbol table
--9724-- object doesn't have a dynamic symbol table
--9724-- Scheduler: using generic scheduler lock implementation.
--9724-- Reading suppressions file: /usr/lib64/valgrind/default.supp
==9724== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-9724-by-ronalfia-on-csl3
==9724== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-9724-by-ronalfia-on-csl3
==9724== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-9724-by-ronalfia-on-csl3
==9724==
==9724== TO CONTROL THIS PROCESS USING vgdb (which you probably
==9724== don't want to do, unless you know exactly what you're doing,
==9724== or are doing some strange experiment):
==9724== /usr/lib64/valgrind/../../bin/vgdb --pid=9724 ...command...
==9724==
==9724== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==9724== /path/to/gdb ./map
==9724== and then give GDB the following command
==9724== target remote | /usr/lib64/valgrind/../../bin/vgdb --pid=9724
==9724== --pid is optional if only one valgrind process is running
==9724==
--9724-- REDIR: 0x4019e10 (ld-linux-x86-64.so.2:strlen) redirected to 0x58059d91 (???)
--9724-- REDIR: 0x4019be0 (ld-linux-x86-64.so.2:index) redirected to 0x58059dab (???)
--9724-- Reading syms from /usr/lib64/valgrind/vgpreload_core-amd64-linux.so
--9724-- Reading syms from /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so
==9724== WARNING: new redirection conflicts with existing -- ignoring it
--9724-- old: 0x04019e10 (strlen ) R-> (0000.0) 0x58059d91 ???
--9724-- new: 0x04019e10 (strlen ) R-> (2007.0) 0x04c2ca70 strlen
--9724-- REDIR: 0x4019d90 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4c2dbc0 (strcmp)
--9724-- REDIR: 0x401aa50 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4c30c40 (mempcpy)
--9724-- Reading syms from /usr/lib64/libc-2.17.so
--9724-- REDIR: 0x4ec6120 (libc.so.6:strcasecmp) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4ec2ea0 (libc.so.6:strnlen) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4ec83f0 (libc.so.6:strncasecmp) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4ec5900 (libc.so.6:memset) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4ec58b0 (libc.so.6:memcpy@GLIBC_2.2.5) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4ec4890 (libc.so.6:__GI_strrchr) redirected to 0x4c2c430 (__GI_strrchr)
--9724-- REDIR: 0x4ecc3b0 (libc.so.6:strchrnul) redirected to 0x4c30760 (strchrnul)
--9724-- REDIR: 0x4ec5ad0 (libc.so.6:__GI_mempcpy) redirected to 0x4c30970 (__GI_mempcpy)
--9724-- REDIR: 0x4ebbef0 (libc.so.6:free) redirected to 0x4c2ac36 (free)
--9724-- REDIR: 0x4ebbad0 (libc.so.6:malloc) redirected to 0x4c29b3c (malloc)
--9724-- REDIR: 0x4ebc4f0 (libc.so.6:calloc) redirected to 0x4c2b8bf (calloc)
--9724-- REDIR: 0x4ec2dc0 (libc.so.6:__GI_strlen) redirected to 0x4c2c9d0 (__GI_strlen)
Running testMapCreateDestroy ... [OK]
--9724-- REDIR: 0x4ec2d70 (libc.so.6:strlen) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4fa5670 (libc.so.6:__strlen_sse2_pminub) redirected to 0x4c2c9b0 (strlen)
--9724-- REDIR: 0x4ec27b0 (libc.so.6:strcpy) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4ed06d0 (libc.so.6:__strcpy_sse2_unaligned) redirected to 0x4c2ca90 (strcpy)
--9724-- REDIR: 0x4ec1320 (libc.so.6:strcmp) redirected to 0x4a24740 (_vgnU_ifunc_wrapper)
--9724-- REDIR: 0x4f74d80 (libc.so.6:__strcmp_sse42) redirected to 0x4c2db70 (__strcmp_sse42)
Running testMapAddAndSize ... [OK]
Running testMapGet ... [OK]
Running testIterator ... [OK]
==9724==
==9724== HEAP SUMMARY:
==9724== in use at exit: 0 bytes in 0 blocks
==9724== total heap usage: 20 allocs, 20 frees, 812 bytes allocated
==9724==
==9724== All heap blocks were freed -- no leaks are possible
==9724==
==9724== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==9724== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

עבור הרצת טסט הדוגמה שהגיע עם התרגיל.
 
האם יש דרך לקרוא מתוך הפלט של הדלג -v על valgrind האם יש קריאות של זיכרון לא מאותחל? לחלופין, האם יש דרכים אחרות לבדוק קריאות של זיכרון לא מאותחל?
 
 
בתגובה ל: רון אלפיה

תשובה ל: קריאת מצביע לא מאותחל

על ידי אורטל כהן בתאריך

היי,

valgrind אכן מוצא שגיאות זכרון, כולל קריאה לזכרון לא מאותחל, או גישה לאזור זכרון לא מוקצה וכדומה.

הדוגמא מטה קוראת לערך לא מאותחל של משתנה m:

#include <stdlib.h>

#include <stdio.h>

 

int main () {

int* m = malloc(sizeof(*m));

if (m == NULL)

return 0;

printf("Should be error: %d\n", *m);

return 0;

}

הפלט בשרת הוא:

 

אבל כשמריצים valgrind הוא כן מחזיר המון שגיאות (כי הערך לא אותחל לפני הגישה למשתנה) - סימנתי ב-bold את השגיאה הרלוונטית:

==25503== Memcheck, a memory error detector

==25503== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==25503== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==25503== Command: ./main

==25503==

==25503== Conditional jump or move depends on uninitialised value(s)

==25503== at 0x4E80C4E: vfprintf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E89498: printf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4005B7: main (in /home/ortalcohen/y/main)

==25503==

==25503== Use of uninitialised value of size 8

==25503== at 0x4E7E31B: _itoa_word (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E825A0: vfprintf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E89498: printf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4005B7: main (in /home/ortalcohen/y/main)

==25503==

==25503== Conditional jump or move depends on uninitialised value(s)

==25503== at 0x4E7E325: _itoa_word (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E825A0: vfprintf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E89498: printf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4005B7: main (in /home/ortalcohen/y/main)

==25503==

==25503== Conditional jump or move depends on uninitialised value(s)

==25503== at 0x4E825EF: vfprintf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E89498: printf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4005B7: main (in /home/ortalcohen/y/main)

==25503==

==25503== Conditional jump or move depends on uninitialised value(s)

==25503== at 0x4E80D1B: vfprintf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E89498: printf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4005B7: main (in /home/ortalcohen/y/main)

==25503==

==25503== Conditional jump or move depends on uninitialised value(s)

==25503== at 0x4E80D9E: vfprintf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4E89498: printf (in /usr/lib64/libc-2.17.so)

==25503== by 0x4005B7: main (in /home/ortalcohen/y/main)

==25503==

Should be error: 0

==25503==

==25503== HEAP SUMMARY:

==25503== in use at exit: 4 bytes in 1 blocks

==25503== total heap usage: 1 allocs, 0 frees, 4 bytes allocated

==25503==

==25503== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1

==25503== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)

==25503== by 0x40058E: main (in /home/ortalcohen/y/main)

==25503==

==25503== LEAK SUMMARY:

==25503== definitely lost: 4 bytes in 1 blocks

==25503== indirectly lost: 0 bytes in 0 blocks

==25503== possibly lost: 0 bytes in 0 blocks

==25503== still reachable: 0 bytes in 0 blocks

==25503== suppressed: 0 bytes in 0 blocks