To get a trial key
fill out the form below
Team License (a basic version)
Enterprise License (extended version)
* By clicking this button you agree to our Privacy Policy statement

Request our prices
New License
License Renewal
--Select currency--
USD
EUR
GBP
RUB
* By clicking this button you agree to our Privacy Policy statement

Free PVS-Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

Message submitted.

Your message has been sent. We will email you at


If you haven't received our response, please do the following:
check your Spam/Junk folder and click the "Not Spam" button for our message.
This way, you won't miss messages from our team in the future.

>
>
OpenMP and exceptions

OpenMP and exceptions

Mar 16 2009
Author:

We continue developing our static analyzer VivaMP and now we would like to speak about diagnosing errors relating to using C++ exceptions in parallel regions. By a parallel region we understand a program fragment which is divided into two threads executed parallel. Parallel executed threads are formed by such OpenMP directives as for and sections.

VivaMP support in PVS-Studio had been canceled in the year 2014. If you have any questions, feel free to contact our support.

You can use exceptions inside parallel regions. But they mustn't leave these parallel regions. Exceptions should be caught and processed inside a parallel region by using try/catch. If the exception leaves the parallel region it will cause fail and most surely program crash. Let's consider an example of incorrect code:

#pragma omp parallel for num_threads(4)
for(int i = 0; i < 4; i++)
{
  //...
  throw 1;
}

This code is incorrect as exceptions will leave the parallel region. To avoid this you should use other mechanisms for transferring information about error occurring. For example, the code may be rewritten as follows:

size_t errCount = 0;
#pragma omp parallel for num_threads(4) reduction(+: errCount)
for(int i = 0; i < 4; i++)
{
  try {
    //...
    throw 1;
  }
  catch (...)
  {
    ++errCount;
  }
}
if (errCount != 0)
  throw 1;

It looks a bit complicated but if you need to use exceptions inside parallel regions, there is no other way and you'll have to create a mechanism like this. But certainly, it's better to try to avoid exceptions.

There is some difficulty in that an exception may call not only your code in which you'll write throw. Exceptions can be generated in functions you use or memory allocating operators as well. Let's consider the following example which at first sight looks safe:

#pragma omp parallel for num_threads(4)
for(int i = 0; i < 4; i++)
{
  float *ptr = new float[10000];
  delete [] ptr;
}

This code can work safely for years and it can cause a program crash if at some moment 'new' operator cannot allocate the needed memory size. According to C++ standard new operator throws std::bad_alloc exception if it cannot allocate the needed memory size. This approach allows us not to check if the necessary memory size has been allocated as we do when using malloc function, and begin to work with it immediately. If memory is not allocated the program will proccess this situation in the necessary place. In case of a parallel region we need some additional work to correctly process the error of memory allocation inside the region itself. This is the corrected example:

#pragma omp parallel for num_threads(4) reduction(+: errCount)
for(int i = 0; i < 4; i++)
{
  try {
    float *ptr = new float[10000];
    delete [] ptr;
  }
  catch (std::bad_alloc &)
  {
    //process error
  }
}

I think you've already guessed that using functions inside parallel sections is also an unsafe and thankless task. Either you are sure that the functions don't generate exceptions or wrap them in try/catch. An unpleasant thing here is that if by the moment of writing parallel code the functions used in it haven't generated an exception, this can change later and you should be very careful.

Summarizing the information, we can say that exceptions are a thing which you should always keep in mind when developing a program using OpenMP. To simplify programmers' life we added three new diagnostic messages into VivaMP which will help you detect errors relating to using exceptions:

V1301. The 'throw' keyword cannot be used outside of a try..catch block in a parallel section

V1302. The 'new' operator cannot be used outside of a try..catch block in a parallel section.

V1303. The FOO function which throws an exception cannot be used in a parallel section outside of a try..catch block.

V1301 diagnostic message indicates the error in the first example while V1302 diagnoses errors of calling 'new' operator outside the exception handler. V1303 is much more complicated. Now VivaMP will warn only about call of functions explicitly marked as throwing exceptions, i.e.:

void MyThrowFoo() throw(...) { }

Functions not marked with can also throw exceptions but they are not considered unsafe. This step is made deliberately to reduce the number of unnecessary warning messages. Otherwise any function call inside the parallel section not screened with try/catch will be unsafe. Although it is really so, it seems that there is little help from such a large number of diagnostic messages. But perhaps VivaMP analyzer will behave in this way in future in "pedantic mode". And in that case functions marked explicitly as not throwing exceptions will be considered safe:

void MyNotThrowFoo() throw() { }

The last thing I would like to say about exceptions in parallel regions is that you should be careful when using barriers. Let's consider the following example:

#pragma omp parallel num_threads (4)
{
  try {
     if (omp_get_thread_num ()  ==  0) {
       throw CException();
     }
     #pragma omp barrier
  }
  catch(CException &) {
  }
}

When an exception is generated one of the threads will "skip" barrier directive and after that a hang will occur. The other threads will eternally wait for the thread in which the exception occurred. Perhaps, in the next version of the analyzer search of the corresponding errors will be added, but at present there are some difficulties of technical character relating to this.

Additional resources

Popular related articles
Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, 10-15% of False Positives

Date: Jul 31 2017

Author: Andrey Karpov

After I wrote quite a big article about the analysis of the Tizen OS code, I received a large number of questions concerning the percentage of false positives and the density of errors (how many erro…
Free PVS-Studio for those who develops open source projects

Date: Dec 22 2018

Author: Andrey Karpov

On the New 2019 year's eve, a PVS-Studio team decided to make a nice gift for all contributors of open-source projects hosted on GitHub, GitLab or Bitbucket. They are given free usage of PVS-Studio s…
The way static analyzers fight against false positives, and why they do it

Date: Mar 20 2017

Author: Andrey Karpov

In my previous article I wrote that I don't like the approach of evaluating the efficiency of static analyzers with the help of synthetic tests. In that article, I give the example of a code fragment…
The Ultimate Question of Programming, Refactoring, and Everything

Date: Apr 14 2016

Author: Andrey Karpov

Yes, you've guessed correctly - the answer is "42". In this article you will find 42 recommendations about coding in C++ that can help a programmer avoid a lot of errors, save time and effort. The au…
The Last Line Effect

Date: May 31 2014

Author: Andrey Karpov

I have studied many errors caused by the use of the Copy-Paste method, and can assure you that programmers most often tend to make mistakes in the last fragment of a homogeneous code block. I have ne…
Static analysis as part of the development process in Unreal Engine

Date: Jun 27 2017

Author: Andrey Karpov

Unreal Engine continues to develop as new code is added and previously written code is changed. What is the inevitable consequence of ongoing development in a project? The emergence of new bugs in th…
Appreciate Static Code Analysis!

Date: Oct 16 2017

Author: Andrey Karpov

I am really astonished by the capabilities of static code analysis even though I am one of the developers of PVS-Studio analyzer myself. The tool surprised me the other day as it turned out to be sma…
PVS-Studio for Java

Date: Jan 17 2019

Author: Andrey Karpov

In the seventh version of the PVS-Studio static analyzer, we added support of the Java language. It's time for a brief story of how we've started making support of the Java language, how far we've co…
Technologies used in the PVS-Studio code analyzer for finding bugs and potential vulnerabilities

Date: Nov 21 2018

Author: Andrey Karpov

A brief description of technologies used in the PVS-Studio tool, which let us effectively detect a large number of error patterns and potential vulnerabilities. The article describes the implementati…
PVS-Studio ROI

Date: Jan 30 2019

Author: Andrey Karpov

Occasionally, we're asked a question, what monetary value the company will receive from using PVS-Studio. We decided to draw up a response in the form of an article and provide tables, which will sho…

Comments (0)

Next comments
This website uses cookies and other technology to provide you a more personalized experience. By continuing the view of our web-pages you accept the terms of using these files. If you don't want your personal data to be processed, please, leave this site.
Learn More →
Accept