2012-04-19 1 views
1

У меня есть функция, и назвать его:При возврате ссылочный GCC добавляет 0x30 в% EAX

Class1& Class2::get() 
{ 
    return *m_ptr; 
} 

Class1& c = m_class2->get(); 

m_ptr обычай смарт-указатель, и я могу видеть в отладчике, что m_ptr.m_p является 0, и я могу см. внутри своего оператора T *, что он действительно возвращает 0. Однако адрес c (& c) не равен NULL, это 0x30! То, что я вижу в разборке:

13059  return *m_ptr; 
eaabbc7e: mov 0x8(%ebp),%eax 
eaabbc81: add $0xb4,%eax 
eaabbc86: mov %eax,(%esp) 
eaabbc89: call 0xea9ce4c0 <operator T*> 
eaabbc8e: add $0x30,%eax 
13060  } 

Непосредственно перед линией добавить $ 0x30,% EAX я могу видеть, что% EAX = 0, то оператор правильно возвращается NULL.

Почему линия для добавления 0x30 здесь ???

+0

Этот вопрос связан? http://stackoverflow.com/questions/6368647/gcc-x64-stack-manipulation – trojanfoe

+0

Ну, я не знаю, я не _that_ большой эксперт в ас. – queen3

+0

Я не уважаю его. Это даже не мой код, но он проверяет, есть ли (& c! = NULL) и & c! = NULL. – queen3

ответ

4

Хотя ответа недостаточно, ваши комментарии подсказывают, что Class2 предполагает множественное наследование, и я буду опасаться, что параметр шаблона T является производным классом, а не Class2.

Таким образом, operator T* возвращает указатель на этот производный класс. Чтобы разыграть его, чтобы дать Class2&, он должен быть преобразован в Class2*, что может включать добавление смещения к указателю, в зависимости от того, как компилятор излагает под-объекты базового класса внутри объекта.

Очевидно, что это допустимо только в том случае, если указатель не равен нулю; это одна из причин, по которой вы никогда не должны разыменовывать нулевой указатель, даже если вы используете результат для инициализации ссылки.

Если функция вернулась Class2*, вы получите нулевой указатель, как ожидалось; это преобразование требуется для преобразования null в null. В вашем случае, поскольку вы вызываете неопределенное поведение в этом случае путем разыменования указателя, компилятору не нужно проверять значение null перед выполнением преобразования.

+0

На самом деле это было наоборот - параметр шаблона T является суперклассом, а Class2 - его базой, но все же это должен быть ответ! – queen3

+0

@ queen3: Да, это имеет больше смысла, чем моя догадка. –

+0

Интересно, что этот код (который портирован на Linux) работает под Windows. Я полагаю, что MS всегда проверяет NULL, даже для ссылок. – queen3

 Смежные вопросы

  • Нет связанных вопросов^_^