Как создать условие гонки в C ++ - PullRequest
0 голосов
/ 26 сентября 2018

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

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

Имеют структуру, имеющую поле массива целых чисел, равное нулю, возможно, длиной 300-500 кБ.Затем из двух потоков скопируйте в него две другие структуры (одна с 1-й, другая с 2-мя), как раз перед тем, как некоторые атомарные памяти выдают барьеры (чтобы убедиться, что неопределенная область поведения завершена, из основного потока, проверив значение атомарной переменной).

Это должно иметь высокий шанс неопределенного поведения, и, возможно, вы могли бы увидеть смешанные 1, 2, (и даже 0?) В нем, чтобы знать, что это произошло.

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

0 голосов
/ 27 сентября 2018

Отличный способ сделать это, вставив своевременные sleep звонки.Это можно использовать, например, для принудительной комбинации событий в порядке, который вы хотите проверить (поток 1 что-то делает, затем поток 2 делает что-то, затем поток 1 делает что-то еще).Недостатком является то, что у вас должно быть представление о том, куда звонить sleep.Сделав это немного, вы должны начать чувствовать это, но вначале помогает какая-то хорошая интуиция.

Вы можете условно вызвать sleep или достичь точки останова из определенного потока, есливы можете получить идентификатор для идентификатора потока.

Кроме того, я почти уверен, что Visual Studio и (я думаю) GDB позволяют вам заморозить некоторые потоки и / или запустить определенные.

0 голосов
/ 27 сентября 2018

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

#include <thread>
#include <assert.h>

int x = 0;

void foo()
{
    while (true)
    {
        x = x + 1;
        x = x - 1;
        assert(x == 0);
    }
}

int main()
{
    std::thread t(foo);
    std::thread t2(foo);

    t.join();
    t2.join();
}

Везде, где я его тестирую, оно довольно быстро утверждает.Затем я мог бы добавить критические разделы, пока утверждение не исчезнет.

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

...