c++ - Invalid free() / delete / delete[] / realloc() error in assignment operator -
i new programming , when trying run program using valgrind getting error this. googled hours solve problem. please can tell me going wrong. hope there mistake near assignment operator.
error:
==5130== invalid read of size 8 ==5130== @ 0x400cfd: std::passwd::~passwd() (passwd.c++:18) ==5130== 0x400c06: main (p1.c++:21) ==5130== address 0x5a1c040 0 bytes inside block of size 8 free'd ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d16: std::passwd::~passwd() (passwd.c++:19) ==5130== 0x400bfa: main (p1.c++:17) ==5130== ==5130== invalid free() / delete / delete[] / realloc() ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d07: std::passwd::~passwd() (passwd.c++:18) ==5130== 0x400c06: main (p1.c++:21) ==5130== address 0x5a1c420 0 bytes inside block of size 8 free'd ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d07: std::passwd::~passwd() (passwd.c++:18) ==5130== 0x400bfa: main (p1.c++:17) ==5130== ==5130== invalid free() / delete / delete[] / realloc() ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d16: std::passwd::~passwd() (passwd.c++:19) ==5130== 0x400c06: main (p1.c++:21) ==5130== address 0x5a1c040 0 bytes inside block of size 8 free'd ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d16: std::passwd::~passwd() (passwd.c++:19) ==5130== 0x400bfa: main (p1.c++:17) ==5130== ==5130== ==5130== heap summary: ==5130== in use @ exit: 120 bytes in 1 blocks ==5130== total heap usage: 7 allocs, 8 frees, 729 bytes allocated ==5130== ==5130== searching pointers 1 not-freed blocks ==5130== checked 192,896 bytes ==5130== ==5130== 120 bytes in 1 blocks still reachable in loss record 1 of 1 ==5130== @ 0x4c2ab80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x53c0024: getdelim (iogetdelim.c:66) ==5130== 0x5444b52: getpass (getpass.c:97) ==5130== 0x400f84: std::passwd::get() (passwd.c++:66) ==5130== 0x400b3c: main (p1.c++:9) ==5130== ==5130== leak summary: ==5130== lost: 0 bytes in 0 blocks ==5130== indirectly lost: 0 bytes in 0 blocks ==5130== possibly lost: 0 bytes in 0 blocks ==5130== still reachable: 120 bytes in 1 blocks ==5130== suppressed: 0 bytes in 0 blocks ==5130== ==5130== error summary: 3 errors 3 contexts (suppressed: 0 0) ==5130== ==5130== 1 errors in context 1 of 3: ==5130== invalid free() / delete / delete[] / realloc() ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d16: std::passwd::~passwd() (passwd.c++:19) ==5130== 0x400c06: main (p1.c++:21) ==5130== address 0x5a1c040 0 bytes inside block of size 8 free'd ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d16: std::passwd::~passwd() (passwd.c++:19) ==5130== 0x400bfa: main (p1.c++:17) ==5130== ==5130== ==5130== 1 errors in context 2 of 3: ==5130== invalid free() / delete / delete[] / realloc() ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d07: std::passwd::~passwd() (passwd.c++:18) ==5130== 0x400c06: main (p1.c++:21) ==5130== address 0x5a1c420 0 bytes inside block of size 8 free'd ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d07: std::passwd::~passwd() (passwd.c++:18) ==5130== 0x400bfa: main (p1.c++:17) ==5130== ==5130== ==5130== 1 errors in context 3 of 3: ==5130== invalid read of size 8 ==5130== @ 0x400cfd: std::passwd::~passwd() (passwd.c++:18) ==5130== 0x400c06: main (p1.c++:21) ==5130== address 0x5a1c040 0 bytes inside block of size 8 free'd ==5130== @ 0x4c2bdec: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5130== 0x400d16: std::passwd::~passwd() (passwd.c++:19) ==5130== 0x400bfa: main (p1.c++:17) ==5130== ==5130== error summary: 3 errors 3 contexts (suppressed: 0 0)
here header file passwd.h
#include<stdio.h> #include<iostream> #ifndef min_passwd_len #define min_passwd_len 6 #endif #ifndef max_passwd_len #define max_passwd_len 20 #endif #ifndef no_of_numbers #define no_of_numbers 1 #endif #ifndef no_of_alphabets #define no_of_alphabets 1 #endif #ifndef no_of_symbols #define no_of_symbols 1 #endif namespace std{ class passwd{ char **pwd; public: passwd& operator=(const passwd); passwd(); ~passwd(); bool check_validity(); void tochar(char **); void get(); }; }
functions above header file: passwd.c++
#include<iostream> #include"passwd.h" #include<string.h> #include<unistd.h> #include<stdlib.h> using namespace std; passwd::passwd() { pwd=(char **)malloc(sizeof(char*)); pwd[0]=(char *)malloc(9); strcpy(pwd[0],"password"); } passwd::~passwd() { free(pwd[0]); free(pwd); } passwd& passwd::operator=(const passwd pswd) { pwd[0]=(char *)realloc(pwd[0],strlen(*pswd.pwd)+1); strcpy(pwd[0],*pswd.pwd); return *this; } bool passwd::check_validity() { if(strlen(pwd[0])<=max_passwd_len&&strlen(pwd[0])>=min_passwd_len); else return false; int number_count=0,alphabet_count=0,symbol_count=0; for(int i=0;i<strlen(pwd[0]);i++) { if(pwd[0][i]<='9'&&pwd[0][i]>='0') { number_count++; } else if((pwd[0][i]>='a'&&pwd[0][i]<='z')||(pwd[0][i]>='a'&&pwd[0][i]<='z')) { alphabet_count++; } else if(pwd[0][i]>32&&pwd[0][i]!=127) { symbol_count++; } } if(number_count>=no_of_numbers&&alphabet_count>=no_of_alphabets && symbol_count>=no_of_symbols) return true; else return false; } void passwd::tochar(char **pswd) { *pswd=(char*)malloc(strlen(pwd[0])+1); strcpy(*pswd,pwd[0]); } void passwd::get() { char *pswd; pswd=getpass(""); pwd[0]=(char *)realloc(pwd[0],strlen(pswd)+1); strcpy(pwd[0],pswd); }
main program: p1.c++
#include"passwd.h" #include<iostream> #include<stdlib.h> int main() { using namespace std; passwd p; cout<<"enter password: "; p.get(); if(p.check_validity()) cout<<"valid pwd.\n"; else cout<<"invalid pwd.\n"; char *s; p.tochar(&s); cout<<s<<endl; passwd x=p; free(s); x.tochar(&s); cout<<s<<endl; free(s); }
your passwd class has implicitly defined copy constructor. if don't explicitly create constructor looks bit like
passwd(const passwd &other)
then compiler automatically generate 1 copies members. when do
passwd x=p;
then x.pwd = p.pwd;
. result, when second passwd
gets destructed, free pwd[0]
, pwd
second time.
to solve this, explicitly define copy constructor want (probably allocate new pwd
, pwd[0]
copy password it). or, alternately, define private copy constructor prevent being used. or if you're using modern constructor can explicitly delete copy constructor passwd(const passwd &other) = delete;
in class declaration. note latter 2 options make passwd x = p;
error.
this breaks if passwd x; x = p;
due issue: operator=
not take reference original, , copy made when invoking it. 1 define operator=(const passwd &pswd)
- leaving out &
copy of argument must made, done using copy constructor, causes double-free after return operator=
, copied pswd
destroyed.
Comments
Post a Comment