overloading - C++ calling completely wrong (virtual) method of an object -


i have c++ code (written else) appears calling wrong function. here's situation:

utf8inputstreamfrombuffer* cstream = foo(); wstring fn = l"foo"; documentreader* reader;  if (a_condition_true_for_some_files_false_for_others) {     reader = (documentreader*) _new gooddocumentreader(); } else {     reader = (documentreader*) _new baddocumentreader(); }  // crash happens inside following call // when baddocumentreader used doc = reader->readdocument(*cstream, fn); 

the files condition true processed fine; ones false crash. class hierarchy documentreader looks this:

class genericdocumentreader {     virtual document* readdocument(inputstream &strm, const wchar_t * filename) = 0; }  class documentreader : public genericdocumentreader {     virtual document* readdocument(inputstream &strm, const wchar_t * filename) {         // stuff     } };  class gooddocumentreader : public documentreader {     document* readdocument(inputstream & strm, const wchar_t * filename); }  class baddocumentreader : public documentreader {     virtual document* readdocument(inputstream &stream, const wchar_t * filename);     virtual document* readdocument(const locatedstring *source, const wchar_t * filename);     virtual document* readdocument(const locatedstring *source, const wchar_t * filename, symbol inputtype); } 

the following relevant:

class utf8inputstreamfrombuffer : public wistringstream {     // foo }; typedef std::basic_istream<wchar_t> inputstream; 

running in visual c++ debugger, shows readdocument call on baddocumentreader calling not

readdocument(inputstream&, const wchar_t*) 

but rather

readdocument(const locatedstring* source, const wchar_t *, symbol) 

this confirmed sticking cout statements in readdocuments. after call source argument of course full of garbage, shortly causes crash. locatedstring have one-argument implicit constructor inputstream, checking cout shows it's not getting called. idea explain this?

edit: other possibly relevant details: documentreader classes in different library calling code. have done complete rebuild of code , problem remained.

edit 2: i'm using visual c++ 2008.

edit 3: tried making "minimally compilable example" same behavior, unable replicate problem.

edit 4:

at billy oneal's suggestion, tried changing order of readdocument methods in baddocumentreader header. sure enough, when change order, changes of functions gets called. seems me confirm suspicion there's weird going on indexing vtable, i'm not sure what's causing it.

edit 5: here's disassembly few lines before function call:

00559728  mov         edx,dword ptr [reader]  0055972e  mov         eax,dword ptr [edx]  00559730  mov         ecx,dword ptr [reader]  00559736  mov         edx,dword ptr [eax]  00559738  call        edx   

i don't know assembly, looks me it's dereferencing reader variable pointer. first thing stored in part of memory should pointer vtable, dereferences eax. places first thing in vtable in edx , calls it. recompiling different orders of methods doesn't seem change this. wants call first thing in vtable. (i have misunderstood this, having no knowledge of assembly @ all...)

thanks help.

edit 6: found problem, , apologize wasting everyone's time. problem gooddocumentreader supposed declared subclass of documentreader, in fact not. c-style casts suppressing compiler error (should have listened you, @sellibitze, if you'd submit comment answer, i'll mark correct). tricky thing code had been working several months pure accident until revision when added 2 more virtual functions gooddocumentreader no longer calling right function luck.

i try removing c-cast first.

  • it unnecessary, casts derived base natural in language
  • it may, actually, cause bug (though it's not supposed to)

it looks compiler bug... not first either in vs.

i unfortunately don't have vs 2008 @ hand, in gcc casts occur correctly:

struct base1 {   virtual void foo() {} };  struct base2 {   virtual void bar() {} };  struct derived: base1, base2 { };  int main(int argc, char* argv[]) {   derived d;   base1* b1 = (base1*) &d;   base2* b2 = (base2*) &d;    std::cout << "derived: " << &d << ", base1: " << b1                                  << ", base2: " << b2 << "\n";    return 0; }   > derived: 0x7ffff1377e00, base1: 0x7ffff1377e00, base2: 0x7ffff1377e08 

Comments

Popular posts from this blog

java - SNMP4J General Variable Binding Error -

windows - Python Service Installation - "Could not find PythonClass entry" -

Determine if a XmlNode is empty or null in C#? -