调用实例变量(即对象)的getter函数时实际发生了什么? [英] What actually happens when calling a getter function for an instance variable(that is an object)?

查看:174
本文介绍了调用实例变量(即对象)的getter函数时实际发生了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我与一个随机引起SEGFAULT的函数有不断的战斗。在尝试找出问题后做了一些额外的工作后,我想出了以下:



通过pastebin发布的所有代码:



BUILD 1:这是原始代码,它导致以下SEGFAULT(在链接之后给出)
http://pastebin.com/huzcqnDA



SEGFAULT:

 #0 6FC657AC libstdc ++  -  6!_ZNKSs4_Rep12_M_is_leakedEv()(Z:\CPP Programming\CodeBlocks\MinGW\bin\libstdc ++  -  6.dll:??)
#1 6FC89FDB libstdc ++ -6!_ZNSs4_Rep7_M_grabERKSaIcES2_()(Z:\CPP Programming\CodeBlocks\MinGW\bin\libstdc ++ - 6.dll:??)
#2 6FC8C0E7 libstdc ++ - 6!_ZNSsC1ERKSs() \CPP Programming\CodeBlocks\MinGW\bin\libstdc ++ - 6.dll:??)
#3 0094A470 Carp :: Sprite :: Sprite(this = 0x27fae8,s = ...) Z:/ CPP编程/ Carperon / Source / Carp / Engine / StructL2.hpp:28)
#4 00944E98 Carp :: Item :: _ spr(this = 0x1277eb80) Carp /.../ Carp / Classes.hpp:59)
#5 00416219 Carp :: WinBag :: update(this = 0x2857f8,o = false)(Z:\CPP Programming\Carperon\Source\\ \\ Carp\Interface.cpp:60)
#6 00419304 Carp :: GameUI :: checkUpdate(this = 0x2857e4)(Z:\CPP Programming \Carperon\Source\Carp\Interface.cpp :240)
#7 00401B7D Carp :: GameApp :: loopGame(this = 0x2801ac)(Z:\CPP Programming\Carperon\main.cpp:35)
#8 00402145 _fu2041 ___ ZSt4cout (Z:\CPP Programming \Carperon\Source\Application.cpp:25)
#9 004017A9 main()(Z:\CPP Programming\Carperon\main.cpp:6)

BUILD 2:这是当前构建,目前导致编译器错误,可能是问题的原因。
http://pastebin.com/89gCjH5P



错误:

  Z:\CPP Programming\Carperon\Source\Carp\Interface.cpp | 57 |错误:不匹配'operator<<'in'std :: operator<< < std :: char_traits< char> >((*&(& st&& st><<< std :: operator< std :: operator< std :: char_traits< char> char>>((*&(& std :: operator<<< std :: char_traits< char>>((*& std :: cout),((const char *) :))) - > std :: basic_ostream< _CharT,_Traits> :: operator <_ char,std :: char_traits< char> 012ItemContainer:))) - > std :: basic_ostream< _CharT,_Traits> :: operator<<?char,std :: char_traits< char>当我调用中给出的getter函数时,字符 

code>,实际发生了什么?我没有看到这里的问题,以前的Q& As,我发现没有解决问题,他们只会导致它打破另一个随机函数。 / p>

最好的我可以称之为这种情况是一个 Heisenbug ,因为这只发生在我在DEBUG模式下的一个不相关的SEGFAULT程序中的其他地方。



我发现唯一可能的帮助是使用const-正确与我的getters,只是带来相同的精确的SEGFAULT到董事会再次(浪费时间进行编译)。



PS我的计划与 Ogre3D 有静态链接,这使我的平均编译时间为5分钟(超过7分钟)如果我更改特定的头)。因此,我需要很长时间才能发布修改/结果。



Carp :: WinBag 与示例代码中给出的 Carp :: Interface 相同(给出错误的类名)



额外注意:我有这个问题发生了5天直接打开和关闭。

:我的情况是由于我自己的懒惰在其他地方的代码:

  ItemPtr temp(new Item(* listItem [1] .get 
temp-> spawnDrop(Coord3(fRAND(-1,1),2,fRAND(-1,1)));
dropList.push_back(temp);
temp.reset(new Item(* listItem [2] .get()));
temp-> spawnDrop(Coord3(fRAND(-1,1),2,fRAND(-1,1)));
dropList.push_back(temp);
temp.reset(newItem(* listItem [3] .get()));
temp-> spawnDrop(Coord3(fRAND(-1,1),2,fRAND(-1,1)));
dropList.push_back(temp);

这样,我创建了一个指向新对象的指针,丢失(内存泄漏任何人?)。这导致了我以后在代码中的所有问题,写这个正确的方式将修复它。



我不敢相信我在这么长一段时间后再次这样做了,更糟糕的是没有意识到...对于任何其他不幸的人来说, strong>请勿。它会给你带来无尽和混乱的压力:*

解决方案

Character不保证Item已经初始化为指针。当你调用它,它只是返回一个指针。如果该指针没有被初始化(或者已经初始化到一个坏的内存位置),试图访问该指针可能导致seg错误:

  Character c; 
Intem * items = c._items(); //获取未初始化的ptr in c
items [foo]; // seg fault(maybe)
pre>

当然,这不是你能在呼叫中得到seg-fault的唯一方法。



你的getter调用中实际发生的是你正在获取一个this指针,对this指针应用偏移量来找到items指针,并返回该值。然而,如果你的this指针是无效的,那么你可以得到seg故障。所以:

 字符* c; //未初始化
c-> _items (可能)

可能导致seg故障。



然而,seg错误并不总是发生:如果指针位置恰好是好的内存,你不会看到seg故障,你只会继续下去未定义的行为模式。



那么你怎么调试这些东西呢?承认,它的屁股的痛苦。这是人们不喜欢C和C ++的主要原因之一,我不认为大多数人会在这里为你寻找。



大多数编译器调试模式将强制未初始化的指针指向一个值。有时,该值位于 hexspeak (我最喜欢的是0xBADF00D)。所以看看你的指针值。 Visual studio初始化指向0xccccccccccccc的指针。



然而,避免这种类型问题的最好方法是使未初始化的指针不可能。使用向量和参考。当你必须使用指针时,坚持智能指针。使用RAIIdesign模式与您的构造函数和析构函数。遵循规则3(或c ++ 11中的3-5规则)。你永远不会(确定你会很少)需要寻找无效的值,因为你使他们难以存在。


Lately I have had a constant battle with a function causing a SEGFAULT randomly. After doing some extra work in trying to find out the problem, I have come up with the following:

All code posted via pastebin:

BUILD 1:This is the original code, it causes the following SEGFAULT (given after link) http://pastebin.com/huzcqnDA

SEGFAULT:

#0 6FC657AC libstdc++-6!_ZNKSs4_Rep12_M_is_leakedEv() (Z:\CPP Programming\CodeBlocks\MinGW\bin\libstdc++-6.dll:??)
#1 6FC89FDB libstdc++-6!_ZNSs4_Rep7_M_grabERKSaIcES2_() (Z:\CPP Programming\CodeBlocks\MinGW\bin\libstdc++-6.dll:??)
#2 6FC8C0E7 libstdc++-6!_ZNSsC1ERKSs() (Z:\CPP Programming\CodeBlocks\MinGW\bin\libstdc++-6.dll:??)
#3 0094A470 Carp::Sprite::Sprite(this=0x27fae8, s=...) (Z:/CPP Programming/Carperon/Source/Carp/Engine/StructL2.hpp:28)
#4 00944E98 Carp::Item::_spr(this=0x1277eb80) (Z:/CPP Programming/Carperon/Source/Carp/../Carp/Classes.hpp:59)
#5 00416219 Carp::WinBag::update(this=0x2857f8, o=false) (Z:\CPP Programming\Carperon\Source\Carp\Interface.cpp:60)
#6 00419304 Carp::GameUI::checkUpdate(this=0x2857e4) (Z:\CPP Programming\Carperon\Source\Carp\Interface.cpp:240)
#7 00401B7D Carp::GameApp::loopGame(this=0x2801ac) (Z:\CPP Programming\Carperon\main.cpp:35)
#8 00402145 _fu2041___ZSt4cout() (Z:\CPP Programming\Carperon\Source\Application.cpp:25)
#9 004017A9 main() (Z:\CPP Programming\Carperon\main.cpp:6)

BUILD 2:This is the current build, currently causes a compiler error, which gives me the idea that this might be the cause of the problem. http://pastebin.com/89gCjH5P

Error:

Z:\CPP Programming\Carperon\Source\Carp\Interface.cpp|57|error: no match for 'operator<<' in 'std::operator<< <std::char_traits<char> >((* &(& std::operator<< <std::char_traits<char> >((* &(& std::operator<< <std::char_traits<char> >((* &(& std::operator<< <std::char_traits<char> >((* & std::cout), ((const char*)"Item Info: ")))->std::basic_ostream<_CharT, _Traits>::operator<< <char, std::char_traits<char> >(a)), ((const char*)"\012ItemContainer: ")))->std::basic_ostream<_CharT, _Traits>::operator<< <char, std::char_traits<char> >(((const void*)((Carp::WinBag*)t|

When I call the getter function given in Character, What is actually happening? I am failing to see what the problem is here, and previous Q&As that I have found do not solve the problem, they only cause it to break another random function later on.

The best I can call this situation is a Heisenbug, since this only occurs when I am in DEBUG mode for an unrelated SEGFAULT somewhere else in the program.

The only possible help I have found is using const-correctness with my getters, only to bring the same exact SEGFAULT to the board again (wasting time into compiling).

P.S. My program has static linkage to Ogre3D, which causes me to have an average compiling time of 5 minutes (more than 7 if I change specific headers). So it will take a long time for me to post edits/results.

P.S. Carp::WinBag is the same as Carp::Interface given in the sample code (gave the wrong class name)

Extra Note: I have had this problem occur for 5 days straight on and off. My sanity can only take so much more of this...

SOLUTION: My situation has been caused from my own laziness somewhere else in the code:

ItemPtr temp(new Item(*listItem[1].get()));
temp->spawnDrop(Coord3(fRAND(-1,1),2,fRAND(-1,1)));
dropList.push_back(temp);
temp.reset(new Item(*listItem[2].get()));
temp->spawnDrop(Coord3(fRAND(-1,1),2,fRAND(-1,1)));
dropList.push_back(temp);
temp.reset(new Item(*listItem[3].get()));
temp->spawnDrop(Coord3(fRAND(-1,1),2,fRAND(-1,1)));
dropList.push_back(temp);

With this, I created a pointer to a new object, BUT at the same time caused the old one to be lost (Memory leak anyone?). This caused all the problems I had later in the code, and writing this the RIGHT way will fix it.

I cannot believe that I did this again after such a long time, and worse NOT realize it... For anyone else that is unfortunate enough to assume this works please DON'T. It will cause endless and confusing stress for you :*

解决方案

Character doesn't make any guarantee that Items has been initialized to a pointer. When you call it, it simply returns a pointer. If that pointer has not been initialized (or has been initialized to a bad memory location), trying to access that pointer may cause a seg fault:

Character c;
Intem* items = c._items();//get uninitialized ptr in c
items[foo];//seg fault (maybe)

Of course, this isn't the only way that you can get a seg-fault in the call.

What is actually happening in your getter call is that you are taking a "this" pointer, applying an offset to the "this" pointer to find the "items" pointer, and returning that value. However, if your "this" pointer is invalid, then you can get a seg fault. So:

Character* c;//not inititialized
c->_items();//seg fault (maybe)

Can cause a seg fault all on its own.

However, seg faults don't always happen: if the pointer location happens to be to good memory you'll not see the seg fault, you'll just continue down into undefined behavior mode.

SO how on earth do you debug these things? Gotta admit, its a pain in the ass. It is one of the primary reasons people dislike C and C++, and I don't think most people here are going to go looking for it for you.

Most compilers in Debug mode will force uninitialized pointers to a value. Sometimes the value is in hexspeak (My favorite being 0xBADF00D). So look at your pointer values. Visual studio initializes pointers to 0xccccccccccccc.

However, the BEST way to avoid this type of problem is to make having uninitialized pointers impossible. Use vectors and references. When you have to use pointers, stick to smart pointers. Use an RAIIdesign patterns with your constructors and destructors. Follow the Rule of 3 (or Rule of 3-5 in c++11). You'll never (ok you'll "rarely") need to look for invalid values because you've made them hard to exist.

这篇关于调用实例变量(即对象)的getter函数时实际发生了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆