<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Feb 23, 2017 at 4:57 PM, Jonathan Roelofs via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
<br>
On 2/23/17 5:24 PM, Larry Gritz via cfe-dev wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi, helpful people. I'm trying to use clang internals to run an in-memory buffer through the C preprocessor (string to string), and I'm having trouble. I wonder if one of you kind souls might be able to spot the problem.<br>
<br>
I cobbled this code together looking at clang's BufferSourceTest.cpp unit test (for the aspect of how to read from a buffer), and for how to invoke just the preprocessor, I looked at the source code for ISPC (<a href="https://github.com/ispc/ispc/blob/master/module.cpp#L2453" rel="noreferrer" target="_blank">https://github.com/ispc/ispc/<wbr>blob/master/module.cpp#L2453</a>).<br>
<br>
The C++11 code below, linked against clang/llvm 3.9, works just fine if I compile my code with clang (any of 3.5, 3.9, 4.0) or with g++ 4.8.5. But when I build my code with g++ 4.9, 5.4, or 6.2, it seems to compile fine but will crash at runtime during the exit of this function, with the following error:<br>
<br>
*** glibc detected *** myapp: double free or corruption (!prev): 0x0000000000a13270 ***<br>
======= Backtrace: =========<br>
/lib/x86_64-linux-gnu/libc.so.<wbr>6(+0x7da26)[0x2ac395bf8a26]<br>
mylib.so(_ZN5clang22CompilerIn<wbr>vocationBaseD1Ev+0xfa)[<wbr>0x2ac3936ecdca]<br>
mylib.so(+0x3718e1)[0x2ac3936e<wbr>88e1]<br>
mylib.so(_ZN5clang16CompilerIn<wbr>stanceD1Ev+0x445)[<wbr>0x2ac3936d8f65]<br>
<br>
This is on Linux. I don't get these errors on OSX, but then again, I am compiling my code with clang there, and it also doesn't seem to crash when I build my code with clang on Linux either. Only with g++, and only when >= 4.9.<br>
<br>
The fact that it crashes for some gcc versions but not others makes me suspicious that it's some misinterpretation of C++11 RAAI, like I'm freeing something that is assumed to be owned by the clang::CompilerInstance. But I'm not sure what that would be.<br>
<br>
Anyway, here's the code. I've simplified a bit by removing the parts that deal with -D and -I directives.<br>
Have I done something foolish here?<br>
<br>
<br>
bool preprocess_buffer (const std::string &buffer,   // Input to be preprocessed<br>
                        const std::string &filename, // Name for reporting errors<br>
                        std::string &result)         // <-- want preprocessed output here<br>
{<br>
    std::unique_ptr<llvm::MemoryBu<wbr>ffer> mbuf (llvm::MemoryBuffer::getMemBuf<wbr>fer(buffer, filename));<br>
<br>
    clang::CompilerInstance inst;<br>
    inst.createDiagnostics();<br>
<br>
    const std::shared_ptr<clang::TargetO<wbr>ptions> &targetopts =<br>
          std::make_shared<clang::Target<wbr>Options>(inst.getTargetOpts())<wbr>;<br>
</blockquote>
<br></span>
This line ^ is extremely suspicious. It makes a shared pointer, takes a *reference* to it, and drops it on the floor. To fix it, get rid of the 'const' and '&' from that line.<br></blockquote><div><br></div><div>While I'd drop the '&' for clarity, that's not the bug: the temporary returned by std::make_shared will be lifetime extended here where it's bound (directly) to a reference.</div><div><br></div><div>-- James</div></div></div></div>