1 year ago

#103571

test-img

Sjoerd Vermeulen

Segfault when assigning to std::unique_ptr<llvm::Module> with make_unique

I've been trying to create a simple compiler using the llvm API in C++, and it used to work fine, until the following snippet of code started to trigger segfaults over and over again:

// codegen.cpp
Status CodeGenerator::generate(...) {
    ...

    // prepare
    _global_init_func_block = nullptr;
    _value_stack = stack<llvm::Value*>();
    _top_module = make_unique<llvm::Module>("top", __context); // this line here (line 12)

    // walk the tree
    ...
}

This is the CodeGenerator class:

// codegen.hpp
#include "pch.h"

#include <stack>

class CodeGenerator: public Visitor
{
    public:
    CodeGenerator(): _builder(__context) {}
    Status generate(string path, const char* source, AST* astree);

    // visitors
    ...

    private:
    string _outfile;
    ErrorDispatcher _error_dispatcher;

    stack<llvm::Value*> _value_stack;
    map<string, llvm::Function*> _functions;

    void error_at(Token *token, string message);
    void warning_at(Token *token, string message);

    void push(llvm::Value* value);
    llvm::Value* pop();

    // llvm-specific

    llvm::IRBuilder<> _builder;
    unique_ptr<llvm::Module> _top_module;
    llvm::BasicBlock* _global_init_func_block;
};

This is the output from Valgrind:

==13652== Conditional jump or move depends on uninitialised value(s)
==13652==    at 0x427641: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::reset(llvm::Module*) (unique_ptr.h:401)
==13652==    by 0x4252BC: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::operator=(std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >&&) (unique_ptr.h:307)
==13652==    by 0x424755: CodeGenerator::generate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char const*, std::vector<StmtNode*, std::allocator<StmtNode*> >*) (codegen.cpp:12)
==13652==    by 0x41D6C3: main (main.cpp:128)
==13652== 
==13652== Conditional jump or move depends on uninitialised value(s)
==13652==    at 0x41FB5C: std::default_delete<llvm::Module>::operator()(llvm::Module*) const (unique_ptr.h:81)
==13652==    by 0x427668: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::reset(llvm::Module*) (unique_ptr.h:402)
==13652==    by 0x4252BC: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::operator=(std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >&&) (unique_ptr.h:307)
==13652==    by 0x424755: CodeGenerator::generate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char const*, std::vector<StmtNode*, std::allocator<StmtNode*> >*) (codegen.cpp:12)
==13652==    by 0x41D6C3: main (main.cpp:128)
==13652== 
==13652== Use of uninitialised value of size 8
==13652==    at 0x55814A1: llvm::Module::~Module() (in /usr/lib/x86_64-linux-gnu/libLLVM-12.so.1)
==13652==    by 0x41FB6A: std::default_delete<llvm::Module>::operator()(llvm::Module*) const (unique_ptr.h:81)
==13652==    by 0x427668: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::reset(llvm::Module*) (unique_ptr.h:402)
==13652==    by 0x4252BC: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::operator=(std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >&&) (unique_ptr.h:307)
==13652==    by 0x424755: CodeGenerator::generate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char const*, std::vector<StmtNode*, std::allocator<StmtNode*> >*) (codegen.cpp:12)
==13652==    by 0x41D6C3: main (main.cpp:128)
==13652== 
==13652== Invalid read of size 8
==13652==    at 0x55814A1: llvm::Module::~Module() (in /usr/lib/x86_64-linux-gnu/libLLVM-12.so.1)
==13652==    by 0x41FB6A: std::default_delete<llvm::Module>::operator()(llvm::Module*) const (unique_ptr.h:81)
==13652==    by 0x427668: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::reset(llvm::Module*) (unique_ptr.h:402)
==13652==    by 0x4252BC: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::operator=(std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >&&) (unique_ptr.h:307)
==13652==    by 0x424755: CodeGenerator::generate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char const*, std::vector<StmtNode*, std::allocator<StmtNode*> >*) (codegen.cpp:12)
==13652==    by 0x41D6C3: main (main.cpp:128)
==13652==  Address 0x6976652e74 is not stack'd, malloc'd or (recently) free'd
==13652== 
==13652== 
==13652== Process terminating with default action of signal 11 (SIGSEGV)
==13652==  Access not within mapped region at address 0x6976652E74
==13652==    at 0x55814A1: llvm::Module::~Module() (in /usr/lib/x86_64-linux-gnu/libLLVM-12.so.1)
==13652==    by 0x41FB6A: std::default_delete<llvm::Module>::operator()(llvm::Module*) const (unique_ptr.h:81)
==13652==    by 0x427668: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::reset(llvm::Module*) (unique_ptr.h:402)
==13652==    by 0x4252BC: std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >::operator=(std::unique_ptr<llvm::Module, std::default_delete<llvm::Module> >&&) (unique_ptr.h:307)
==13652==    by 0x424755: CodeGenerator::generate(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char const*, std::vector<StmtNode*, std::allocator<StmtNode*> >*) (codegen.cpp:12)
==13652==    by 0x41D6C3: main (main.cpp:128)
==13652==  If you believe this happened as a result of a stack
==13652==  overflow in your program's main thread (unlikely but
==13652==  possible), you can try to increase the size of the
==13652==  main thread stack using the --main-stacksize= flag.
==13652==  The main thread stack size used in this run was 8388608.
==13652== 
==13652== HEAP SUMMARY:
==13652==     in use at exit: 288,939 bytes in 2,685 blocks
==13652==   total heap usage: 2,888 allocs, 203 frees, 438,662 bytes allocated
==13652== 
==13652== LEAK SUMMARY:
==13652==    definitely lost: 29,906 bytes in 52 blocks
==13652==    indirectly lost: 0 bytes in 0 blocks
==13652==      possibly lost: 0 bytes in 0 blocks
==13652==    still reachable: 259,033 bytes in 2,633 blocks
==13652==         suppressed: 0 bytes in 0 blocks
==13652== Rerun with --leak-check=full to see details of leaked memory
==13652== 
==13652== Use --track-origins=yes to see where uninitialised values come from
==13652== For lists of detected and suppressed errors, rerun with: -s
==13652== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

I genuinly do not know why this started to happen as I didn't change anything in the generate function. I tried to backtrace what change in the code made this happen but I cannot find it. All my google searches have been in vain as well.

EDIT: I've solved it by rewriting the initialization of the CodeGenerator object. Still don't know why the segfault got triggered but at least it's solved now.

c++

llvm

llvm-ir

llvm-c++-api

0 Answers

Your Answer

Accepted video resources