我有一个构造函数,它接收一个字符指针。如果它是空的,我需要将其成员变量设置为NULL,但是,当我尝试时程序在退出时崩溃。
我已经确认它到达了将其设置为NULL的行,这是导致崩溃的原因。
我尝试了以下内容:
val = NULL;
val = 0;
val = "";
这些都导致崩溃,但是如果我使用:
val = new Char[1];
val = "o";
它并没有崩溃。
有什么我不做的事吗?
更新
以下是我的问题的快速更新。
我正在使用的析构函数是:
~LField() {
if (val)
delete[] val;
}
如果我拿出来:
if (val)
delete[] val;
然后程序在退出时不会崩溃:
val = "";
以下是更多代码:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = "", bool canEditVal = true) {
if(strlen(valVal) > 0) {
//doesn't jump in here since valVal is empty
}
else {
val = ""; // this is where I'm trying to set a NULL value
}
}
LField(const LField &clone) {
if (val)
delete[] val;
val = new char[strlen(clone.val)];
strcpy(val, clone.val);
rowNum = clone.rowNum;
colNum = clone.colNum;
width = clone.width;
canEdit = clone.canEdit;
index = clone.index;
}
LField& operator=(const LField &lfieldobj) {
if (this != &lfieldobj) {
if (val)
delete[] val;
val = new char[strlen(lfieldobj.val)];
strcpy(val, lfieldobj.val);
rowNum = lfieldobj.rowNum;
colNum = lfieldobj.colNum;
width = lfieldobj.width;
canEdit = lfieldobj.canEdit;
index = lfieldobj.index;
}
return *this;
}
修改:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = NULL, bool canEditVal = true) {
if(valVal != NULL) {
}
else {
val = NULL;
}
}
LField(const LField &clone) {
delete[] val;
if (clone.val != NULL) {
val = new char[strlen(clone.val) + 1];
strcpy(val, clone.val);
}
else
val = NULL;
rowNum = clone.rowNum;
colNum = clone.colNum;
width = clone.width;
canEdit = clone.canEdit;
index = clone.index;
}
LField& operator=(const LField &lfieldobj) {
if (this != &lfieldobj) {
delete[] val;
if (lfieldobj.val != NULL) {
val = new char[strlen(lfieldobj.val) + 1];
strcpy(val, lfieldobj.val);
}
else
val = NULL;
rowNum = lfieldobj.rowNum;
colNum = lfieldobj.colNum;
width = lfieldobj.width;
canEdit = lfieldobj.canEdit;
index = lfieldobj.index;
}
return *this;
}
~LField() {
delete[] val;
}
我已经更新了代码。现在val要么用new []分配内存,要么是NULL,所以delete []不应该有问题。但是,它在退出时仍会崩溃。
答案 0 :(得分:10)
在复制构造函数中,您尝试delete[]
未初始化的指针:
LField(const LField &clone) {
//good code here, then...
if (val) //<+ some random address here
delete[] val;//<-undefined behavior
}
不要那样做,跳过整个构造。在单元化对象上调用复制构造函数,没有资源可以“释放”。
此外,您尝试delete[]
字符串文字,这是未定义的行为。请尝试以下更改:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = "", bool canEditVal = true) {
if(strlen(valVal) > 0) {
//doesn't jump in here since valVal is empty
}
else {
val = new char[1];
*val = 0;
}
}
以下是缓冲区溢出:
val = new char[strlen(whatever)]; <-forgot to +1 for the null terminator
strcpy(val, whatever);
在不需要delete[]
之前检查空指针 - 空指针上的delete[]
是合法的并且没有效果。
答案 1 :(得分:4)
一个:
LField(const LField &clone) {
if (val)
delete[] val;
这是愚蠢的,因为val未定义。您将在随机存储器上调用delete []。
B:
val = new char[strlen(clone.val)];
strcpy(val, clone.val);
c-type字符串需要一个null终止符。你需要新的[]和附加字节。
答案 2 :(得分:3)
您可能正在尝试访问代码中的某个位置(取消引用)val
仍然引用NULL
。
确保您的代码中没有位置
val=NULL; //in the constructor
//somewhere in your code
char ch= *val; //This would be Undefined Behavior
您正在delete[]
上调用val
,其值为""
(字符串文字),这是未定义的行为。
UB的一些例子
1)
char *p="hello";
delete p; //UB
delete []p; //UB
2)
char *p==new char[20]("Hello");
delete p; //UB
delete []p; //fine
3)
char *p=new char('a');
delete []p; //UB
delete p; //fine
答案 3 :(得分:2)
调用
delete[] NULL;
delete[] 0;
没关系,你甚至不需要空检查。 但是打电话给
delete[] "whatever";
不正常,因为此char *未使用new []分配。
请注意,调用字符串函数(如strlen()就像在构造函数中完成一样,在null引用中是非法的。
在第一次分配之前,您可以在构造函数中访问val。这也可能导致未定义的行为。
答案 4 :(得分:0)
我和Prasoon Saurav在一起。您展示的代码看起来不错,所以问题出在其他地方。
试试这个:
val = 0;