Опасно ли вызывать функцию и передавать ей ограниченный указатель?

Рассмотрим эти две функции:

void foo(char * __restrict localPtr)
{
// some work with localPtr
}

void bar(char * __restrict ptr)
{
// some work with ptr
foo(_ptr);
// some other work with ptr
}

Как ptr был объявлен __restrict в bar, звонит foo() опасно? Под опасным я имею в виду, что зона памяти, указанная localPtr перекрывается ptrодин. Каковы рекомендации по этому поводу?

0

Решение

restrict квалификатор означает, что единственный способ для вызываемой функции получить доступ к памяти, переданной как localPtr в foo через этот указатель; в этой памяти нет псевдонимов. Это может позволить оптимизатору создавать лучший код, потому что ему не нужно беспокоиться о другом указателе, также изменяющем данные.

В этом контексте и в большинстве других restrict Квалификатор возлагает на вас ответственность, программист, выполняющий вызовы, чтобы убедиться, что вы соблюдаете требование «без псевдонимов».

Там нет видимой опасности от кода выше.

Обратите внимание, что чаще всего у вас есть несколько указателей в списке аргументов, когда restrict используется. Из стандарта C сравните:

void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memmove(void *s1, const void *s2, size_t n);

Первый (memcpy()) говорит, что куски памяти [s1 .. s1+n-1] а также [s2 .. s2+n-1] не должен перекрываться; вы получите неопределенное поведение, если они действительно перекрываются. Второй (memmove()) не навязывает это требование.


Но это не призыв к foo() создание другого указателя, который изменяет данные?

Да, нет, вроде … но в основном нет.

Указатель в foo() безусловно передается bar(), но пока bar() работает, единственный путь bar() можно получить в память через указатель, он был передан. таким образом bar() может быть скомпилирован при условии, что у него нет псевдонима для памяти, с которой он работает.

Когда компилятор обрабатывает foo(), он знает (гарантирует), что после аргументов bar() оцениваются и перед вызовом функции, и другим, когда функция возвращается. Он знает, что данные могли быть изменены bar() так как это не было передано const char *, Поэтому он сгенерирует код для учета этих возможностей. Тем не менее, компилятор также знает, что единственный способ, которым foo() может получить доступ к памяти, адресуемой localPtr через localPtr (вот что restrict говорит), и это может продолжаться на основе этого предположения.

Итак, есть вторая копия указателя, а bar() называется, но это не является нарушением правил restrict в любом случае.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]