Kebocoran memori dan kesalahan valgrind dalam loop for kecil ini?

Saya mengalami masalah dengan bagian kecil kode yang menghasilkan kesalahan di valgrind. Ketika saya mengomentari kode dan menjalankan valgrind, saya tidak mendapatkan kebocoran atau kesalahan memori apa pun sehingga loop ini yang menjadi penyebabnya:

///Print the top users
    const char* str;
    for (int i = 0; i < count; i++) {
        if (FinalArray[i].Score == -1) {
            break;
        }

        int id = UserGetID(user);
        char* name = UserGetName(user);
        int finalID = UserGetID(FinalArray[i].user);
        char* finalName = UserGetName(FinalArray[i].user);

        assert(finalName!= NULL && name !=NULL);
        str = mtmSuggestFriends(id, name, finalID, finalName);

        if (str == NULL) {
            return MAIN_ALLOCATION_FAILED;
        }

//      fprintf(fileOutput, str);
    }

setelah loop ini saya hanya mengembalikan enum yang menyatakan sukses.

Berikut kesalahan di Valgrind:

==8779== Use of uninitialised value of size 8
==8779==    at 0x4037C2: UserGetName (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x401FAC: SuggestFriends (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x402E6D: executeUserCommand (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x40281B: main (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779== 
==8779== Use of uninitialised value of size 8
==8779==    at 0x4037A0: UserGetID (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x401FC8: SuggestFriends (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x402E6D: executeUserCommand (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x40281B: main (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779== 
==8779== Invalid read of size 1
==8779==    at 0x403F1A: mtmSuggestFriends (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x401FEE: SuggestFriends (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x402E6D: executeUserCommand (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x40281B: main (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==  Address 0x9848B4458BB44589 is not stack'd, malloc'd or (recently) free'd
==8779== 
==8779== Process terminating with default action of signal 11 (SIGSEGV)
==8779==  General Protection Fault
==8779==    at 0x403F1A: mtmSuggestFriends (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x401FEE: SuggestFriends (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x402E6D: executeUserCommand (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779==    by 0x40281B: main (in /u1/023/mtm/ex2/RUN/mtm_isocial)
==8779== 
==8779== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 4 from 1)
==8779== malloc/free: in use at exit: 1,250 bytes in 93 blocks.
==8779== malloc/free: 455 allocs, 362 frees, 10,081 bytes allocated.
==8779== For counts of detected errors, rerun with: -v
==8779== searching for pointers to 93 not-freed blocks.
==8779== checked 122,512 bytes.
==8779== 
==8779== LEAK SUMMARY:
==8779==    definitely lost: 0 bytes in 0 blocks.
==8779==      possibly lost: 0 bytes in 0 blocks.
==8779==    still reachable: 1,250 bytes in 93 blocks.
==8779==         suppressed: 0 bytes in 0 blocks.
==8779== Reachable blocks (those to which a pointer was found) are not shown.
==8779== To see them, rerun with: --show-reachable=yes

Fungsi ToStringUser mengembalikan malloc dari const char*.. Jadi saya tidak perlu khawatir untuk membebaskannya kan?

Adakah yang tahu mengapa ini terjadi?

Saya mencoba membebaskan str dengan kode ini tetapi saya tetap mendapatkan kesalahan yang sama dan jumlah kebocoran memori yang sama:

free((char*) str); OR free((void*) str);

Berikut adalah struct dari Pengguna dan getID dan getName:

struct User_t {
    char *Name;
    int ID;
    int Birth;
};
int UserGetID(User user) {
    return user->ID;
}
char* UserGetName(User user) {
    return user->Name;
}

Sebelum loop saya menginisialisasi Pengguna baru dengan ini:

User user = FindUserPointer(setUser, id);

Fungsi yang digunakan adalah ini:

static User FindUserPointer(Set users, int ID) {
        assert(users!=NULL);
    User tmpUser = UserCreate("temp", ID, 99);
    if (tmpUser == NULL) {
        return NULL;
    }
    SET_FOREACH(User,Itrator1,users) {
        if (UserCompare(tmpUser, Itrator1) == 0) {
            UserFree(tmpUser);
            return Itrator1;
        }
    }
    UserFree(tmpUser);
    return NULL;
}

person Omar    schedule 04.05.2012    source sumber
comment
kenapa kamu tidak khawatir tentang membebaskannya?   -  person msam    schedule 04.05.2012
comment
Anda harus selalu khawatir tentang mengosongkan memori.   -  person Philip    schedule 04.05.2012
comment
Apa yang dimaksud dengan user dalam perulangan for? Dan program melakukan segfault pada fungsi mtmSuggestFriends, jadi mungkin berguna untuk melihatnya.   -  person huon    schedule 04.05.2012
comment
@msam bahkan jika saya membebaskannya dengan melemparkan str ke void* atau char*, saya terus mendapatkan kesalahan ini dan 93 blok memori bocor.   -  person Omar    schedule 04.05.2012
comment
@dbaupp Saya membuat pengguna dan mendapatkan penunjuk ke pengguna tersebut di awal fungsi ini (sebelum loop): Pengguna pengguna = FindUserPointer(setUser, id);. Mengenai mtmSuggestFriends, itu ada dalam file objek dan saya tidak memiliki kodenya meskipun itu seharusnya tidak menjadi penyebab masalah karena teman saya tidak mengalami masalah dalam menggunakannya.   -  person Omar    schedule 04.05.2012
comment
@Philip Bagaimana cara membebaskan const..? Bahkan ketika saya membebaskan strwith cast saya mendapatkan kesalahan dan kebocoran memori. Pertanyaan diperbarui   -  person Omar    schedule 04.05.2012
comment
@Omar, Programnya mogok. Kebocoran Anda adalah masalah lain.   -  person IanNorton    schedule 04.05.2012
comment
@Omar: Dengan memanggil free() di atasnya ;) Perhatikan bahwa free() tidak mengubah nilai argumennya, meskipun itu tidak masalah.   -  person Philip    schedule 04.05.2012
comment
@Philip Saya mendapatkan kesalahan ini ketika membebaskan str tanpa pemeran: meneruskan argumen 1 dari 'gratis' membuang kualifikasi 'const' dari tipe target penunjuk   -  person Omar    schedule 04.05.2012
comment
@Omar, programnya mogok (itulah maksud Invalid read of size 1 + SIGSEGV), Anda harus memperbaikinya sebelum Anda terlalu khawatir tentang freeing memori.   -  person huon    schedule 04.05.2012
comment
@Omar: Anda benar. Saya mencarinya, dan solusi idiomatisnya adalah tidak menggunakan pointer const untuk menyimpan hasil malloc(). Lagipula itu tidak masuk akal, karena Anda akan mengubah (yaitu free()) penunjuk setelahnya.   -  person Philip    schedule 04.05.2012
comment
@Philip Masalahnya adalah sesuatu yang lain. Saya keluar dari batas susunan. ketika saya memperbaikinya, saya tidak mengalami kesalahan atau kebocoran memori. Saya tidak perlu mengosongkan const.. saya kira itu dibebaskan secara otomatis :). Terima kasih atas bantuannya kepada Anda dan semua orang lainnya!   -  person Omar    schedule 04.05.2012


Jawaban (3)


Valgrind tidak mengeluh tentang kebocoran - ia mengeluh bahwa Anda membaca memori yang tidak diinisialisasi dan mendereferensi pointer yang tidak valid (pointer deref yang tidak valid membuat program mogok - setidaknya di bawah Valgrind).

Kita perlu melihat UserGetID() dan UserGetName() untuk memiliki harapan dalam menentukan bug di dalamnya (tapi itu mungkin masih belum cukup).

Berdasarkan komentar Anda bahwa mtmSuggestFriends adalah file objek yang sumbernya tidak Anda miliki, tebakan saya adalah UsetGetID() dan/atau UserGetName() meneruskan pointer yang tidak valid ke mtmSuggestFriends.

person Michael Burr    schedule 04.05.2012
comment
Pertanyaan diperbarui dengan kode. mtmSuggestFriends adalah fungsi dalam file objek. itu mallocs dan mengembalikan const char*. Bukan itu penyebab kebocorannya, karena banyak teman saya yang menggunakannya dan 0 kebocoran saat menggunakannya. - person Omar; 04.05.2012
comment
Saya memperbarui loop for dengan pernyataan (lihat kode di atas) dan masih berfungsi. - person Omar; 04.05.2012
comment
Sekarang kita tahu lebih banyak, tapi tidak tahu seperti apa data yang diteruskan ke FindUserPointer() atau apa itu SET_FOREACH(). Namun berdasarkan uraian Anda tentang mtmSuggestFriends, masalahnya mungkin heapnya rusak. Mungkin UserCreate() memiliki bug (mungkin tidak mengalokasikan cukup memori untuk memasukkan terminator nol pada string Name?). - person Michael Burr; 04.05.2012
comment
@Omar: menelusuri loop dalam debugger. Saya berani bertaruh pada suatu saat name berakhir menjadi non-NULL tetapi menunjuk ke memori yang tidak masuk akal/tidak valid. Itu masih akan melewati assert(), tapi tidak akan membuat mtmSuggestFriends() bahagia. - person Michael Burr; 04.05.2012
comment
Saya melakukan itu, dan saya menemukan bahwa tes yang kami dapatkan menginginkan lebih banyak pengguna daripada yang sebenarnya saya miliki, jadi saya harus memeriksa jumlah_pengguna yang diterima ke jumlah maksimal yang dapat saya cetak (dan tidak lebih).. Jadi saya keluar dari FinalArray batas. Saya menambahkan if(..) kecil, dan sekarang saya tidak mengalami kebocoran memori atau kesalahan. Terima kasih atas bantuan Michael. - person Omar; 04.05.2012

Pertama, Anda meneruskan pointer user yang belum ditetapkan. Kemudian fungsi SuggestFriends() Anda yang dipanggil dari UserGetID() menggunakan penunjuk sampah yang penuh keacakan ini sebagai penunjuk nyata yang mengarah ke pembacaan yang tidak valid (SEGV)

Anda mungkin menemukan bahwa menyetel "peringatan sebagai kesalahan" (-Werr di gcc) mungkin akan menunjukkan di mana Anda melakukan hal-hal yang tidak terduga.

person IanNorton    schedule 04.05.2012
comment
Saya memperbarui kode dengan penugasan pengguna. Saya men-debug kode dengan gerhana dan pengguna bukan NULL ketika mencapai kesalahan ini. - person Omar; 04.05.2012
comment
tepatnya, ini bukan NULL, ini adalah nilai yang bukan merupakan penunjuk yang valid, mungkin dari mana valgrind mengeluh tentang penggunaan variabel yang tidak diinisialisasi. Anda harus SELALU menginisialisasi pointer ke NULL. - person IanNorton; 04.05.2012
comment
Saya mencoba dengan ini: Pengguna user = NULL; pengguna= TemukanUserPointer(setUser, id); Apakah ini yang kamu maksud? Saya masih mendapatkan kesalahan yang sama. Saya juga mencoba mengembalikan SALINAN pengguna di FindUserPointer, tetapi tetap saja smae. - person Omar; 04.05.2012

struct User_t {
char *Name;
int ID;
int Birth;
};
int UserGetID(User user) {
    return user->ID;
}

...dan di mana User didefinisikan?

person msam    schedule 04.05.2012