Путаница с возвратом адреса объекта - PullRequest
3 голосов
/ 23 июня 2011

У меня есть следующий код (какой-то код удален, чтобы разделить его до самого необходимого; пара используемых методов / атрибутов должна быть самоочевидной):

void testApp::togglePalette(){
    GraphicalEntity* palette= this->getEntityByName("palette-picker");
    cerr << palette << endl;
}

GraphicalEntity* testApp::getEntityByName(string name){
    list<GraphicalEntity*>::iterator j;
    for(j=screenEntities.begin(); j!=screenEntities.end();++j){
        if ((*j)->getTypetag() == name){
            cerr << *j << endl;
            return *j;
        }
    }
}

Что выводит следующее:

0x54bda0
0

Я в замешательстве - почему palette в togglePalette() не совпадает с адресом, возвращаемым из getEntityByName (то есть 0x54bda0 в текущем случае), а 0?

Спасибо!

РЕДАКТИРОВАТЬ: Как Фред указал в одном из своих комментариев, это был действительно вопрос о том, что компилятор был сбит с толку кодом, достигающим конца функции без возврата чего-либо.

Добавление:

return (GraphicalEntity*) NULL;

в конце моего getEntityByName метода решил проблему. Большое спасибо!

Меня все еще смущает, почему метод возвращает 0, даже если объект найден (как в том, как я реализую свой код, известно, что всегда найдется что-то найденное), хотя - любое объяснение этого будет более чем приветствоваться!

Ответы [ 2 ]

2 голосов
/ 23 июня 2011

Следуя моему комментарию, вот более полный ответ.

В вашем методе testApp::getEntityByName() есть путь, где элемент управления выходит из метода без возврата значения. В зависимости от вашего компилятора, архитектуры и соглашения о вызовах это может привести к тому, что машинный код не будет работать , даже если ваш поток никогда не проходит по ошибочному пути .

В зависимости от соглашения о вызовах, вызывающий или вызывающий метод несут ответственность за очистку стека до или после возврата метода. Возвращаемое значение и то, где оно размещено в памяти, является частью этого соглашения, и компилятор ожидает, что функция всегда будет возвращать один и тот же тип независимо от того, какой поток управления внутри функции. Из-за этого он может оптимизировать некоторые методы, переставляя некоторые вещи и генерируя специальный код очистки, чтобы очистить восстановление стека в соответствии с соглашением о вызовах. В любом случае, пропущенное возвращаемое значение может испортить эту оптимизацию или очистку, потому что это нарушает то, что компилятор считал само собой разумеющимся, когда обрабатывал ваш код, то есть каждый путь возвращал указатель на объект GraphicalEntity. Неудачное предположение повредило стек или его содержимое, и вы в итоге получили указатель NULL (он мог бы также разбиться или сделать что-то еще, все это является частью неопределенного поведения ).

0 голосов
/ 23 июня 2011

Это может произойти, если доступ к screenEntities осуществляется через другой поток, поэтому «подборщик паллет» был удален или изменен. Тогда функция getEntityByName вернет NULL в режиме отладки.

...