Можно ли явно указать функции, чтобы она не принимала указатели на переменные, не относящиеся к куче? - PullRequest
0 голосов
/ 29 августа 2011

Я заметил, что g ++ достаточно умен, чтобы определить, когда функция возвращает указатель на временную / локальную переменную, например,

int *foobar()
{
      int a;
      return &a;
}

В результате:

 warning: address of local variable ‘a’ returned
* 1006Есть ли способ, которым я могу определить прототип функции, чтобы принимать только указатели, которые компилятор может сказать, не являются временными.Допустим, у меня есть функция
 barfoo(int *a_int);

Есть ли способ сказать g ++, чтобы он жаловался, если кто-то передает в него указатель на локальный / временный объект?Это запретило бы людям вызывать barfoo с неверными указателями и потенциально спасало бы отладку некоторых раздражающих проблем.

Пример:

   void barfoo(int *a)
   {
        cerr << a << endl;
   };

   void foobar()
   {
        int a;
        barfoo(&a);
   }

Я бы хотел, чтобы компилятор жаловался на `barfoo (& a) '.

Ответы [ 7 ]

1 голос
/ 29 августа 2011

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

int a;
...
do_something (&a);
printf ("%d\n", a);
0 голосов
/ 30 августа 2011

В c ++ вы можете написать шаблонный класс «гарантированный указатель кучи», который содержит один действительный указатель внутри, но имеет жестко ограниченные конструкторы, так что единственный способ создать его - new.Перегрузите достаточно операторов, и вы могли бы заставить его вести себя почти как голый указатель, за исключением того, что он не будет преобразовывать из такого указателя.

(У меня есть сомнения относительно того, будет ли этохотя стоит потраченных усилий).

0 голосов
/ 30 августа 2011

Никогда, никогда не используйте сырые указатели в C ++ без уважительной причины. В этом случае, поскольку вы планируете стать владельцем указателя, примите объект, который отражает это. Либо auto_ptr \ unique_ptr, если вы хотите единоличное владение, либо shared_ptr в противном случае. Если вы не вступаете в права собственности, примите (возможно, постоянную) ссылку.

0 голосов
/ 30 августа 2011

Я не думаю, что есть какой-то способ заставить компилятор принудительно применить его, но вы можете обнаружить некоторые экземпляры раньше, используя malloc_size.

void someFunc(int * mustBeHeap) {
   assert(0!=malloc_size(mustBeHeap));
   //do stuff
}

К сожалению, вы получите ложные срабатывания из кода, подобного этому:

void someOtherFunc() {
    int * myInts=(int *)malloc(sizeof(int)*20);
    someFunc(&(myInts[3]));
}

Это не будет работать слишком хорошо с чем-либо, выделенным с помощью new, boost :: pool и т. Д. Фактически, вы получите ложные срабатывания практически от всего.

Такжеmalloc_size не является стандартным.

Редактировать:

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

0 голосов
/ 29 августа 2011

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

0 голосов
/ 29 августа 2011

Вы можете указать gcc обрабатывать предупреждения как ошибки с опцией -Werror. Или сделайте указанное предупреждение как ошибку -Werror=. 3.8 Варианты запроса или отмены предупреждений .

0 голосов
/ 29 августа 2011

Нет, это может быть абсолютно полезным, чтобы делать то, что вы хотите избежать там.GCC / G ++ не может догадаться, что функция, принимающая ссылку / указатель, сохранит ее где-то для последующего повторного использования, когда исходный вызывающий функции уже покинул стек вызовов.

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