C++ 赋值运算符中的free()/delete/delete[]/realloc()错误无效
我是编程新手,当我试图使用Valgrind运行程序时,我遇到了这样的错误。我用谷歌搜索了几个小时来解决这个问题。你能告诉我哪里出了问题吗。希望赋值运算符附近有错误 错误:C++ 赋值运算符中的free()/delete/delete[]/realloc()错误无效,c++,valgrind,free,C++,Valgrind,Free,我是编程新手,当我试图使用Valgrind运行程序时,我遇到了这样的错误。我用谷歌搜索了几个小时来解决这个问题。你能告诉我哪里出了问题吗。希望赋值运算符附近有错误 错误: ==5130== Invalid read of size 8 ==5130== at 0x400CFD: std::passwd::~passwd() (passwd.c++:18) ==5130== by 0x400C06: main (p1.c++:21) ==5130== Address 0x5a1c04
==5130== Invalid read of size 8
==5130== at 0x400CFD: std::passwd::~passwd() (passwd.c++:18)
==5130== by 0x400C06: main (p1.c++:21)
==5130== Address 0x5a1c040 is 0 bytes inside a block of size 8 free'd
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D16: std::passwd::~passwd() (passwd.c++:19)
==5130== by 0x400BFA: main (p1.c++:17)
==5130==
==5130== Invalid free() / delete / delete[] / realloc()
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D07: std::passwd::~passwd() (passwd.c++:18)
==5130== by 0x400C06: main (p1.c++:21)
==5130== Address 0x5a1c420 is 0 bytes inside a block of size 8 free'd
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D07: std::passwd::~passwd() (passwd.c++:18)
==5130== by 0x400BFA: main (p1.c++:17)
==5130==
==5130== Invalid free() / delete / delete[] / realloc()
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D16: std::passwd::~passwd() (passwd.c++:19)
==5130== by 0x400C06: main (p1.c++:21)
==5130== Address 0x5a1c040 is 0 bytes inside a block of size 8 free'd
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D16: std::passwd::~passwd() (passwd.c++:19)
==5130== by 0x400BFA: main (p1.c++:17)
==5130==
==5130==
==5130== HEAP SUMMARY:
==5130== in use at exit: 120 bytes in 1 blocks
==5130== total heap usage: 7 allocs, 8 frees, 729 bytes allocated
==5130==
==5130== Searching for pointers to 1 not-freed blocks
==5130== Checked 192,896 bytes
==5130==
==5130== 120 bytes in 1 blocks are still reachable in loss record 1 of 1
==5130== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x53C0024: getdelim (iogetdelim.c:66)
==5130== by 0x5444B52: getpass (getpass.c:97)
==5130== by 0x400F84: std::passwd::get() (passwd.c++:66)
==5130== by 0x400B3C: main (p1.c++:9)
==5130==
==5130== LEAK SUMMARY:
==5130== definitely 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 from 3 contexts (suppressed: 0 from 0)
==5130==
==5130== 1 errors in context 1 of 3:
==5130== Invalid free() / delete / delete[] / realloc()
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D16: std::passwd::~passwd() (passwd.c++:19)
==5130== by 0x400C06: main (p1.c++:21)
==5130== Address 0x5a1c040 is 0 bytes inside a block of size 8 free'd
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D16: std::passwd::~passwd() (passwd.c++:19)
==5130== by 0x400BFA: main (p1.c++:17)
==5130==
==5130==
==5130== 1 errors in context 2 of 3:
==5130== Invalid free() / delete / delete[] / realloc()
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D07: std::passwd::~passwd() (passwd.c++:18)
==5130== by 0x400C06: main (p1.c++:21)
==5130== Address 0x5a1c420 is 0 bytes inside a block of size 8 free'd
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D07: std::passwd::~passwd() (passwd.c++:18)
==5130== by 0x400BFA: main (p1.c++:17)
==5130==
==5130==
==5130== 1 errors in context 3 of 3:
==5130== Invalid read of size 8
==5130== at 0x400CFD: std::passwd::~passwd() (passwd.c++:18)
==5130== by 0x400C06: main (p1.c++:21)
==5130== Address 0x5a1c040 is 0 bytes inside a block of size 8 free'd
==5130== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5130== by 0x400D16: std::passwd::~passwd() (passwd.c++:19)
==5130== by 0x400BFA: main (p1.c++:17)
==5130==
==5130== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
这是头文件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();
};
}
#包括
#包括
#ifndef最小通行长度
#定义最小路径长度6
#恩迪夫
#ifndef MAX_PASSWD_LEN
#定义最大路径长度20
#恩迪夫
#ifndef编号的编号
#定义编号1中的无编号
#恩迪夫
#ifndef无字母表
#定义字母表1中的无字母
#恩迪夫
#ifndef无任何符号
#定义一个或多个\u符号1
#恩迪夫
名称空间标准{
类密码{
字符**pwd;
公众:
passwd&运算符=(const passwd);
passwd();
~passwd();
bool check_validity();
void tochar(字符**);
void get();
};
}
上述头文件的函数: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);
}
#包括
#包括“passwd.h”
#包括
#包括
#包括
使用名称空间std;
passwd::passwd()
{
pwd=(char**)malloc(sizeof(char*);
pwd[0]=(char*)malloc(9);
strcpy(pwd[0],“密码”);
}
passwd::~passwd()
{
自由(pwd[0]);
免费(pwd);
}
passwd&passwd::operator=(const passwd pswd)
{
pwd[0]=(char*)realloc(pwd[0],strlen(*pswd.pwd)+1;
strcpy(pwd[0],*pswd.pwd);
归还*这个;
}
bool passwd::检查_有效性()
{
如果(strlen(pwd[0])=MIN\u PASSWD\u LEN);
其他的
返回false;
整数计数=0,字母计数=0,符号计数=0;
对于(int i=0;i='a'和&pwd[0][i]='a'和&pwd[0][i]32和&pwd[0][i]!=127)
{
符号_计数++;
}
}
如果(数字计数>=无数字和字母计数>=无字母和符号计数>=无符号)
返回true;
其他的
返回false;
}
void passwd::tochar(字符**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);
}
主程序:P1.C+++P/>
#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);
}
#包括“passwd.h”
#包括
#包括
int main()
{
使用名称空间std;
密码;
cout您的passwd类有一个隐式定义的复制构造函数
passwd(const passwd &other)
然后,编译器会自动生成一个简单地复制所有成员的编译器
passwd x=p;
然后有效地执行x.pwd=p.pwd;
。因此,当第二个passwd
被破坏时,您可以再次释放pwd[0]
和pwd
要解决此问题,请显式定义一个复制构造函数,该构造函数执行您希望它执行的操作(可能会分配一个新的pwd
和pwd[0]
,然后将密码复制到其中)。或者,也可以定义一个私有副本构造函数以防止使用它。或者,如果您使用的是现代构造函数,则可以使用类声明中的passwd(const-passwd&other)=delete;
显式删除副本构造函数。请注意,后两个选项将使passwd x=p;
出错
由于另一个问题,即使您执行了passwd x;x=p;
,也会出现这种情况:您的运算符=
没有引用原始值,因此在调用它时会创建一个副本。通常会定义运算符=(const passwd&pswd)
-通过省略&
必须制作参数的副本,这是使用复制构造函数完成的,然后在您从操作符=
返回后导致双重释放,并且复制的pswd
被销毁。如果我们也能看到passwd
源文件,这将有所帮助。我添加了passwd源文件I hOP错误主要是由于赋值x= p++在C++中使用新的和删除而不是Malc。更好的是使用STD::Strugs:严重错误的第一件事是定义命名空间<代码> STD < /C> >,这是留给编译器的。第二件事是,你使用了一组<代码>定义为< /Cult> s而不是常量。然后,你的头文件缺少包含保护,但这是次要的。最后,在C++中,有一个重要的规则,它被称为“三定律”。。在web上做一些研究,你绝对必须了解这个规则。如果我将行passwd x=p;
更改为passwd x;x=p;
?它必须正常工作??但仍然不好,在0x400D39:std::passwd::~passwd()(passwd.c++:18)显示以下错误,大小为8==7140==Invalid read==7140==by 0x400C31:main(p1.c++:22)==7140==Address 0x5a1c040是大小为8 free'd的块内的0字节==7140==at 0x4C2BDEC:free(in/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)==7140==by 0x400D52:std::passwd:~passwd()(passwd.c++:19)==7140==by 0x400BD0:main(p1.c++:18)`由于operator=
采用的是按值对象,而不是引用,因此在调用operator=
的过程中会调用复制构造函数,因此同样的问题最终也会发生。您能告诉我为什么要传递引用而不是复制变量吗