Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this dangling-gsl warning invoked?

I am analyzing a codebase with clang-tidy and see a warning I do not understand. The warning is invoked by the following lines of code:

void fun(const QString& bar) {
    const char* c_format = bar.toStdString().c_str();
    expand_some_macro(c_format);
}

c_format is passed around in the expanded macro which reads as follows:

#define expand_some_macro(c_format)\
    char buffer[MAX_SIZE];\
    va_list args;\
    va_start(args, c_format);\
    vsnprintf(buffer, MAX_SIZE, _TRUNCATE, c_format, args);\
    va_end(args);

which includes function calls from the shlobj header that I do not understand at this point. The clang-tidy generates the following warning:

warning: object backing the pointer will be destroyed at the end of the full-expression [clang-diagnostic-dangling-gsl]

I browsed the web, in particular the c++ core guidelines, in an attempt to educate myself about this warning but could not find a proper reference. This lead me to two sets of questions:

  1. What is a reference for this warning? Where can I learn about this an similar warnings?
  2. What might be wrong with the code above? Do I need to call delete[] c_format at the end of the scope?
like image 978
fabian Avatar asked Jan 25 '23 11:01

fabian


1 Answers

Consider the statement...

const char* c_format = bar.toStdString().c_str();

bar.toStdString() returns a temporary std::string which will be destroyed before the next statement. But you then call std::string::c_str() against that temporary variable and save its return value to be used in...

expand_some_macro(c_format);

So, by the time c_format is used in the above expression the memory it points to has already been released when the temporary std::string was destroyed. Hence the warning.

However, without knowing what your macro does (or why it needs to be a macro) it's difficult to say much more.

Edit:

By way of clarification, the code you have currently could be rewritten (more or less) as...

const char* c_format = nullptr;
{
    std::string str = bar.toStdString();
    c_format = str.c_str();
}
expand_some_macro(c_format);

So you're using the memory pointed to by c_format beyond its lifetime.

like image 90
G.M. Avatar answered Feb 04 '23 13:02

G.M.