Возможно ли это изменение порядка выполнения
Как мы знаем, компилятор или ЦП могут изменить порядок выполнения по своему усмотрению, только если они следуют правилу «как если бы». Например, если у нас есть такой кусок кода:
C = A + B;
D = E + F;
Компилятор или ЦП могут выполнять
D = E + F
перед
C = A + B
. Я могу понять, что.
Сегодня мой коллега попытался создать библиотеку журналов на C++. Его идея состоит в том, чтобы использовать конструктор и деструктор для создания журналов с помощью некоторых потоковых функций перегрузки, таких как
operator<<()
.
В основном он предлагал такой класс:
class Log
{
public:
Log() { streamObj << "start: " << getCurrentTime() << endl; }
~Log() { streamObj << "end: " << getCurrentTime() << endl; }
};
Теперь я пользователь библиотеки журналов. Мой коллега сказал мне, что я могу использовать библиотеку, как показано ниже:
void func()
{
Log log;
// do something1
// do something2
// do something3
return;
}
Поэтому, когда выполняется первая строка, вызывается конструктор, чтобы я мог получить «начало» в журнале. И когда функция вернется, будет вызван деструктор, поэтому я получу
end
в журнале. С помощью объекта мы можем четко найти начало функции и конец функции.
Звучит ясно и здорово.
Однако, как я упоминал в начале поста, машина может изменять порядок вещей по своему усмотрению. Итак, мне теперь интересно, возможно ли, что конструктор вызывается позже, чем мы думаем, и / или деструктор вызывается раньше, чем мы думаем, так что
log
не может работать так, как мы ожидали. Я имею в виду, код
func
выглядело так, как указано выше, но когда он был скомпилирован или выполнен, реальный порядок стал следующим:
// do something1
Log log;
// do something2
// call the destructor of `log`
// do something3
return
Кстати, поток в классе
Log
направляется куда-то еще, например, в файл, в общую память или в TCP-сокет.
Так я разумный? Или такого переупорядочивания никогда не будет? Если это может случиться, есть ли какой-нибудь способ запретить такое переупорядочение или какой-то метод, предлагающий полезную библиотеку журналов, которая может сообщить нам начало и конец любой функции?
Фактически, я слышал о некоторых новых методах в C++11, таких как
std::atomic
и
std::atomic_thread_fence
. Насколько я понимаю, если такой вид переупорядочивания возможен, мне может понадобиться ... забор?
class Log
{
public:
Log() {
streamObj << "start: " << getCurrentTime() << endl;
// build a fence here!
}
~Log() { streamObj << "end: " << getCurrentTime() << endl; }
};
Я правда не знаю, возможно ли это ...