在编写本机c ++代码时,我看到同样的程序在xcode(iOS)中工作得很好,尽管在eclipse(android)中崩溃了。我可以找到问题代码,这是由于内存访问不良造成的。我想知道为什么xcode(iOS)没有遇到同样的错误访问因此崩溃。
实际上我创建了一个类“class_A”,它继承了其他类,比如class_B。稍后在代码中我创建了相同的类实例指针并分配了函数foo()的返回对象(属于class_B),它返回超类型的对象,即class_B。
代码段...
class class_A : public class_B
{
public:
};
class_A *tempPart = (class_A *)class_A::foo("abc.png");
if(tempPart)
{
-------------------
--------------------
}
现在,在访问_tempPart时,程序崩溃了android(eclipse),但xcode(iOS)总能正常工作。我可以弄清楚,因为fn foo()返回类型为class_B的对象,因此我将一个超类(较小大小的对象)class_B的对象分配给继承的类(一个更大的对象)Class_A的对象,因此它导致了一个糟糕的内存访问。
但我无法弄清楚为什么在xcode(iOS)上看不到同样的问题。 我是xcode和c ++的新手,所以请帮助我理解这一点。
答案 0 :(得分:2)
未定义的行为未定义。
执行诸如访问无效内存之类的操作会导致C ++中出现未定义的行为。结果可能经常是崩溃,但C ++并不保证这样的事情。相反,程序可能只是表现得很奇怪,或者甚至完全按照您的意图行事,没有任何错误迹象。不同的实现可能会做不同的事情。
这里有一些信息可以帮助解释为什么C ++有未定义的行为(而不像Java那样非常难以排除未定义行为的语言)。
每位C程序员应该了解的未定义行为
从你的描述中并不完全清楚出现了什么问题。你说一些关于将较大的对象分配给较小的对象导致错误的内存访问的事情,然而这不是C ++中的赋值方式,并且示例代码仍然使用指针。以下代码完全合法且定义明确,例如:
struct B {};
struct D : B {
int i;
void foo() { i = 100; }
};
B b = D(); // works fine, does not overwrite anything outside b. Slicing occurs.
B *bar() {
return new D;
}
D *d = (D*)bar(); // works fine because the dynamic type matches.
出现问题的地方是:
B *baz() { return new B; }
D *d = (D*)baz(); // not okay, undefined behavior. Anything can happen now, later, or even before this point.
d->foo(); // might crash, might not.
因此,假设这是您的程序正在执行的操作,Java中的相同错误被定义为导致异常。在Objective-C中,消息传递机制将尝试在运行时查找选择器的实现,如果它没有找到任何内容,则会发生“无法识别的选择器”异常。
答案 1 :(得分:0)
@ Bames53回答说,这是未定义的行为。快速解决方法是使class_B::foo
成为模板函数并按如下所示重写
template <class ReturnClassType>
ReturnClassType *foo(std::string str){
然后您将其称为
class_A::foo<class_A>("abc.png");
如果你使用公共/受保护的函数来初始化返回的对象,这应该可行。
答案 2 :(得分:0)
您无法安全地将B向上转换为A. B没有_useShader成员。你只能这样做:B * = A *,但不是A * = B *。您可能想为A对象创建单独的工厂方法。