Это хорошо, чтобы отправить выделенный объект стека в качестве параметра указателя на какую-то другую функцию? - PullRequest
7 голосов
/ 13 апреля 2009

Хорошо ли отправлять выделенный в стеке объект в качестве параметра указателя на какую-то другую функцию?

Ответы [ 6 ]

12 голосов
/ 13 апреля 2009

Да, но более распространенной идиомой C ++ для этой ситуации является использование ссылки (и, вероятно, ссылки на const) вместо указателя. Так что вместо

void foo( sometype * p ) {
   p->func();
}

Вы пишете:

void foo( sometype & p ) {
   p.func();
}

Это имеет то преимущество, что вам не нужно разыменовывать объект в вызывающей стороне:

void afunc() {
   sometype t;
   foo( t );
}

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

10 голосов
/ 13 апреля 2009

Если вы уверены, что вызов является синхронным, то вполне допустимо отправить адрес выделенного стека объекта в функцию. В случае, если вызов асинхронный (т. Е. Вызванная вами функция передает указатель в другой поток), он определенно создаст проблемы, поскольку вы можете попытаться получить доступ к адресу памяти из другого потока даже после уничтожения выделенного стека объекта.

6 голосов
/ 13 апреля 2009

Пока принимающая функция не предполагает, что она получает право собственности на ресурс (и пытается освободить его), конечно. Ссылка может быть лучшей идеей, хотя.

2 голосов
/ 13 апреля 2009

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

void store(int* param) {
     // Store pointer in some global storage for further use
     global_storage.add_param(param); 
}
void func() {
    int test_var = 5;
    store(&test_var); // Pass the pointer to the global storage
} 
// At this point stack object test_var will be destroyed
// Global storage contains a pointer, that points to some garbage
2 голосов
/ 13 апреля 2009

Это прекрасно для синхронного вызова функции. Если вызов асинхронный, это может привести к сбою при удалении объекта стека, когда он выходит из области видимости.

1 голос
/ 13 апреля 2009

Это, конечно, верно, но со многими оговорками. Вот главные моменты, о которых следует помнить (некоторые уже упоминались другими, некоторые нет).

  • Указатель сам по себе может означать, что владение ресурсом передается вызываемому (то есть они должны освободить его после использования). Здесь ссылка на месте.
  • Во многих ситуациях функция, которую вам нужно вызвать, уже определена, и вы не можете ее изменить, вы должны изучить ее поведение и убедиться, что она не предполагает, что она будет владеть объектом, хранить его статически или копировать в другое место.
  • Если вызываемая функция должна получить нулевой указатель, указывающий на отсутствие указанного параметра, у вас не будет выбора использовать ссылку.
  • Асинхронные вызовы абсолютно запрещены (если, конечно, вы не заблокируете их до тех пор, пока они не будут выполнены с использованием локального объекта, а затем вернетесь).
  • Вызываемая функция никогда не должна ни при каких обстоятельствах обращаться за пределы размера рассматриваемого объекта, это разрушит ваш стек и почти наверняка приведет к краху вашей программы!
  • Вызов функции, чувствительной к доступу к байту, превышающему размер объекта, может быть обязанностью безопасности. На самом деле, это самый распространенный способ взлома защищенных систем. Это называется переполнением буфера. (выходит за рамки вашего вопроса, но вы можете прочитать больше здесь и здесь )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...