指针工作,然后似乎无缘无故地中断
Pointer Works And Then Breaks Seemingly Without Reason
为什么我可以在分配函数的作用域内时访问分配指针后访问对象中保存的数据,但一旦我尝试通过同一指针访问相同的值,但在该函数之外就不能了?
指针是一个成员函数,在函数内分配。在函数中,工作正常。但是,当从该函数中调用另一个使用类作用域的函数时,指针行为异常,呈现垃圾数据。为什么?
法典:
#include <iostream>
class Object{
public:
Object( ) { std::cout << "Object constructor called." << std::endl; }
Object( const Object &in ) { i = in.i; std::cout << "Object copy constructor called." << std::endl; }
~Object( ) { std::cout << "Object destructor called." << std::endl; }
int i;
};
class ObjectManager{
public:
Object * retObject(){
Object *myObject = new Object;
myObject->i=55;
return myObject;
}
};
class LogicManager{
public:
LogicManager(){
myObjectManager = new ObjectManager;
}
~LogicManager(){
delete myObjectManager;
}
Object * retObject(){
return myObjectManager->retObject();
}
private:
ObjectManager *myObjectManager;
};
class Viewer{
public:
~Viewer( ) { if( myObject ) { delete myObject; } }
void ptrinObject( LogicManager * inLogic ){
myObject = inLogic->retObject();
std::cout << "Got path size of " << myObject->i << std::endl; //correct
std::cout << "Got path size of " << retObjectVal( ) << std::endl; //0?!?!?!?
}
int retObjectVal( ) { myObject->i; }
private:
Object *myObject;
};
int main(){
LogicManager myManager;
Viewer myViewer;
//myViewer.cpyinObject( &myManager );
myViewer.ptrinObject( &myManager );
return 0;
}
输出:
Object constructor called.
Got path size of 55
Got path size of 861280848
Object destructor called.
问题是:
int retObjectVal( ) { myObject->i; }
该函数中没有return
语句。你只有一个没有副作用的表情。结果,我们遇到了 §6.6.3/2:
它从函数末尾流出等效于没有值的返回;这导致未定义 值返回函数中的行为。
返回的内容是未定义的行为,因此它最终返回了一些垃圾。只需制作:
int retObjectVal() { return myObject->i; }
这是一个容易犯的错误,这就是为什么您应该始终尝试使用尽可能高的警告设置进行编译的原因。例如,在没有标志的 gcc 上,我没有收到任何警告。但是有了-Wall
,我得到:
警告:语句无效 [-Wunused-value]
警告:函数中没有返回语句返回非 void [-Wreturn 类型]
首先,你没有初始化Viewer::myObject
所以如果你只是这样做
void something() {
Viewer v;
}
您最终可能会尝试删除无效指针。
myViewer.cpyinObject( &myManager );
myViewer.ptrinObject( &myManager );
这两个函数都会创建一个新Object
但都不会检查是否已分配一个(内存泄漏)。然后,他们立即忽略创建的新对象,而是分配另一个由ObjectManager
分配的新Object
(更多内存泄漏)。
最后,Viewer::retObjectVal
实际上并没有专门return
一个值,因此您会收到"函数末尾的垃圾"。
我建议你看看你的编译器警告,因为任何明智的编译器都会警告你我提到的第一个和第三个问题。
在Viewer
类中,您缺少一个return
语句:
int retObjectVal( ) { return myObject->i; }
应该工作。
您拥有的是一种方法,其中某些分支在不返回值的情况下脱落。这会导致未定义的行为。你只是在评估"myObject->i;"作为一个语句。
您可能应该解决的另一个问题是,您的 Object 指针不属于任何人,也不会在任何地方删除。也就是说,您正在删除ObjectManager
但它没有任何地方delete
基础对象本身。您可能应该在那里找出一个所有权模型,让某人跟踪这些指针,并在适当的时候delete
它们。
- 类成员和中断
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- 我的代码运行良好,但在游戏循环中中断
- 使用带有MCP23017的 pigpio 进行中断读取
- 为什么我在 AVR 中的中断无法正常工作?
- 使用 UDP 中断 while()-循环
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- 如何在 CompleteAsyncIO 中访问 IOMemoryBufferDescriptor,该描述符通过中断 EP
- 如何为伺服电机创建中断或返回值?
- 开关:无外壳中断
- 如何使用中断停止循环?
- 当我使用CHAR_INFO结构时,控制台会无缘无故地改变颜色
- 为什么当我输入一个被接受的数字时,我的 do-while 循环没有中断?
- 在 Ubuntu 中编译 SuiteSparse,在安装 CHOLMOD 时中断
- 在PROGMEM中添加更多数据会中断Arduino Mega 2560上的SPI传输
- 附加到 gdb 会中断并且不会继续该过程
- 使用 shared_ptr 在中断时结束多线程循环
- 调用函数时,变量突然无缘无故地更改
- 无缘无故地抛出实例
- 指针工作,然后似乎无缘无故地中断