Указатели, хранящие информацию во время вызовов функций - PullRequest
0 голосов
/ 25 марта 2011

Я немного смущен тем, что происходит с моими указателями между вызовами функций.Это не то, что я ожидал.У меня следующая ситуация:

SomeClass *p1= 0, *p2 = 0;
SomeMethod(p1, p2);
printf("P1 total: %d\n", p1->total); // crashes
printf("P2 total: %d\n", p2->total); // crashes

// method someMethod, where the values of the pointers are valid
void SomeMethod(SomeClass *p1, SomeClass *p2)
{
    someMethodThatModifiesThePointers(&p1, &p2);
    printf("P1 total: %d\n", p1->total); // prints valid value
    printf("P2 total: %d\n", p2->total); // prints valid value
};

Как видно из моих комментариев, свойство .total указателя (целое число) допустимо внутри метода, но больше не действует вне его.Почему это так?Указатели не должны терять область действия.

Если быть точным, someMethodThatModifiesThePointers() - это opencv's cvExtractSURF.Я вытащил код, чтобы сделать его простым.

Ответы [ 4 ]

3 голосов
/ 25 марта 2011

C - язык передачи по значению.Это означает, что указатели в вашей исходной функции не могут быть изменены при вызове на SomeMethod() (кстати, C не имеет методов).Вы рушитесь в закомментированных строках, потому что p1 и p2 все еще являются нулевыми указателями в то время.

То же самое касается указателей внутри SomeMethod().Ваши строки, прокомментированные prints valid value, потерпят крах по той же причине, если вы передадите нулевые указатели на SomeMethod().Для вас невозможно получить результат, который вы говорите, по крайней мере, учитывая код, который вы показали.Если вы допустили ошибку в своем примере и хотели, чтобы эта строка была:

    someMethodThatModifiesThePointers(&p1, &p2);

Это может сработать так, как вы объясните - p1 и p2 затем передаются по ссылке (чтото есть, вы передаете указатель на указатель по значению), и их значения могут быть действительными внутри SomeMethod().Однако исходные копии p1 и p2 в вашем верхнем коде все равно будут содержать нулевые указатели.

Вы можете решить проблему, выполнив то же самое - передайте p1 и p2 вSomeMethod() по ссылке:

 SomeMethod(&p1, &p2);

Это изменение потребует от вас внесения некоторых изменений в SomeMethod():

void SomeMethod(SomeClass **p1, SomeClass **p2)
{
    someMethodThatModifiesThePointers(p1, p2);
    printf("P1 total: %d\n", (*p1)->total);
    printf("P2 total: %d\n", (*p2)->total);
};

После этого вызова p1 и p2 inВаша верхняя функция будет вести себя так, как вы хотите.

0 голосов
/ 25 марта 2011

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

SomeClass *p1= 0, *p2 = 0;
SomeMethod(p1, p2);
printf("P1 total: %d\n", p1->total); // crashes
printf("P2 total: %d\n", p2->total); // crashes

// method someMethod, where the values of the pointers are valid
void SomeMethod(SomeClass *p3, SomeClass *p4)
{
    someMethodThatModifiesThePointers(&p3, &p4);
    printf("P3 total: %d\n", p3->total); // prints valid value
    printf("P4 total: %d\n", p4->total); // prints valid value
};

Указатели p1 и p2 копируются в p3 и p4 соответственно, но не наоборот.

0 голосов
/ 25 марта 2011

свойство указателя .total (целое число) допустимо внутри метода, но больше не действует вне его. Почему это так?

Учитывая тот факт, что он печатает действительное значение внутри SomeMethod, печатает действительное значение и вылетает при возврате SomeMethod, я предполагаю, что оба p1,p2 переданы по значению . По возвращении SomeMethod оба p1,p2 являются нулевыми указателями , и разыменование это объясняет сбой. Вам необходимо разместить код someMethodThatModifiesThePointers(p1, p2);.

0 голосов
/ 25 марта 2011

То, что происходит ...

Вы : создать указатель на «экземпляр» SomeClass.

GCC : нет проблем!готово.

Вы : присвойте 0x0 в качестве значения для этого указателя.То есть «объект», на который он указывает, находится в памяти в позиции 0x0

GCC : все в порядке, 0x0 не принадлежит вашей программе, но я буду использовать его.

Вы : хорошо.Затем сделайте что-нибудь с моим новым экземпляром SomeClass!Скомпилируйте и запустите!

Операционная система : WOAH WOAH, подождите секунду, бастер.Вы должны были подумать об использовании malloc(), чтобы сначала попросить у меня память.Эта позиция памяти 0x0 принадлежит мне, а не вам.Ошибка общей защиты, amigo, наслаждайтесь сбоями.

(Кстати, термины «класс», «экземпляр» и т. Д. Являются терминами объектно-ориентированного программирования, они не совсем принадлежат C. Мы обычнопоговорим о структурах, функциях и указателях здесь:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...