Доступ к объекту с автоматической продолжительностью хранения из другого потока - PullRequest
5 голосов
/ 28 апреля 2019

Я наткнулся на этот вопрос: Доступ к потоку к стеку другого потока .Связанный вопрос касается простого C, но мой основной язык - C ++, поэтому я попытался выяснить, применяются ли те же правила к C ++.

Я нашел этот раздел в черновике C11 N1570:

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

Я считаю, что соответствующий разделиз C ++ 20 черновик N4810 равен [basic.stc.auto] и в нем не упоминается этот случай.В этой части черновик C ++ 11 содержит тот же текст, что и C ++ 20.

Под [intro.multithread] Я нашел это предложение со сноской:

Каждая тема впрограмма потенциально может получить доступ к каждому объекту и функции в программе.

Объект с автоматическим или продолжительным хранением потока (6.6.5) связан с одним конкретным потоком и может быть доступен для другого потока только косвенно черезуказатель или ссылка (6.7.2).

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

1 Ответ

2 голосов
/ 28 апреля 2019

Вы правы, строка, которую вы цитировали для C ++, фактически устанавливает, что все потоки в программе C ++ видят одно и то же адресное пространство.Одним из краеугольных камней объектной модели C ++ является то, что каждый живой объект имеет уникальный адрес [intro.object] / 9 .Основываясь на [intro.multithread] / 1 , вы можете передать указатель или ссылку на объект, созданный в автоматическом или локальном хранилище одного потока, в другой поток и получить доступ к объекту из этого второго потока, покаобъект гарантированно существует, и нет гонок данных…

Интересно, что стандарт C явно не дает подобных гарантий.Однако тот факт, что разные объекты имеют разные адреса, а адрес объекта одинаков с точки зрения каждого потока в программе, все равно может показаться неявным и необходимым следствием правил языка.C18 указывает, что адрес живого объекта не изменяется [6.2.4 / 2], любой указатель объекта можно сравнить с указателем на void [6.5.9 / 2], и два указателя сравнивают равные, если и толькоесли они указывают на один и тот же объект [6.5.9 / 6].Класс хранения не является частью типа указателя.Таким образом, указатель, указывающий на объект в автоматическом хранилище одного потока, должен сравнивать неравный с указателем на некоторый другой объект в автоматическом хранилище другого потока, а также с указателем, указывающим на некоторый объект с другой продолжительностью хранения.И любые два указателя, указывающие на один и тот же объект в автоматическом хранилище какого-либо потока, должны сравниваться одинаково, независимо от того, откуда и каким образом эти указатели получили эти указатели.Таким образом, не может быть, чтобы значение указателя означало что-то другое в разных потоках.Даже если это может быть определено реализацией, может ли данный поток действительно получить доступ к объекту в автоматическом хранилище другого потока через указатель, я могу, например, сделать глобальный void*, назначить ему указатель на объект автоматического храненияиз одного потока, и, учитывая необходимую синхронизацию, попросите другой поток наблюдать этот указатель и сравнивать его с другим указателем.Стандарт гарантирует мне, что сравнение может быть истинным, только если я сравниваю его с другим указателем, который указывает на тот же объект, то есть тот же объект в автоматическом хранилище другого потока, и что в этом случае оно должно быть истинным…

Я не могу дать вам точного обоснования решения оставить его определяемым реализацией, может ли один поток обращаться к объектам в автоматическом хранилище другого потока.Но можно представить гипотетическую платформу, где, например, только потоку, для которого был выделен стек, предоставляется доступ к страницам этого стека, например, по соображениям безопасности.Я не знаю ни одной реальной платформы, где это было бы так.Однако ОС может легко это сделать даже на x86.C уже основан на некоторых, возможно, довольно сильных предположениях относительно адресной модели.Я думаю, это хорошее предположение, что комитет по стандартам C просто пытался избежать добавления каких-либо дополнительных ограничений поверх этого ...

...