Search code examples
cmakec++17rapidjson

Why is my simplified version of rapidjson/example/serialize/serialize.cpp throwing a segmentation fault?


I am blocking on a problem I have tried to resolve for 2 days now..

I want to use rapidjson along with libpqxx/pistache to insert/read json data from an API call / from the database. I tried a simple version of the serialize example just to get hang of it, but it throws a seg fault..

On linux mint 19 (Tara), I complied my code (I put the relevant code in main.cc) using CMake/Make and C++17.

Here is the folder tree:

/home/[user]/Documents/algoEngine/library/sources/main.cc /home/[user]/Documents/algoEngine/library/sources/library.cc /home/[user]/Documents/algoEngine/library/headers/library.hh /usr/local/include/rapidjson /usr/local/lib/libpqxx.so /usr/local/lib/libpistache.so

My CMakeLists.txt file:


    cmake_minimum_required(VERSION 3.10.2)
    project(algoEngine)

    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_EXTENSIONS OFF)

    # fmax-errors => max number of errors displayed at compile time
    # GCC_COMPILE_FLAGS = can append several desired option of gcc. For example: "-fmax-errors=3 -Wall"
    set(GCC_COMPILE_FLAGS "-fmax-errors=3 -g")
    set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COMPILE_FLAGS}")

    # adding preprocessor values..
    add_compile_definitions(RAPIDJSON_HAS_STDSTRING=1)

    #However, the file(GLOB...) allows for wildcard additions:
    file(GLOB SOURCES_LIBRARY "${CMAKE_SOURCE_DIR}/library/sources/*.cc")

    # remove libraryBridge.cc from SOURCES_LIBRARY
    list(REMOVE_ITEM SOURCES_LIBRARY "${CMAKE_SOURCE_DIR}/library/sources/libraryBridge.cc") 

    add_executable(algoLibrary ${SOURCES_LIBRARY})


    target_include_directories(algoLibrary PUBLIC ${CMAKE_SOURCE_DIR}/library/headers)   # might be useless with find_package just below? 

    find_package(RapidJSON)

    target_link_libraries(algoLibrary pistache pqxx)

    set(CMAKE_INSTALL_RPATH "/usr/local/lib")
    set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

    ######################## INSTALL CONFIGURATION ######################## 
    # create conf directory
    set(algoLibraryInstallDir "/usr/local/bin/algoLibrary")

    file(GLOB algoLibraryConfFiles "${CMAKE_SOURCE_DIR}/library/conf/*Library*.conf")

    install(TARGETS algoLibrary DESTINATION ${algoLibraryInstallDir})
    install(FILES ${algoLibraryConfFiles} DESTINATION ${algoLibraryInstallDir}/conf)

My main.cc file (I modified the file to only have the test I want. Normally, I would instantiate a "Library" class which contains a http server with Pistache)


    #include "library.hh"
    // for test purpose, to remove..
    #include "rapidjson/document.h"
    #include "rapidjson/stringbuffer.h"
    #include "rapidjson/prettywriter.h"
    #include "rapidjson/writer.h"

    using namespace std;
    using namespace rapidjson;

    int main(int argc, char* argv[]) {
      const char* json = "{\"address\":\"127.0.0.1\", \"port\":9100}";
      Document doc;
      doc.Parse(json);

      StringBuffer jsonBuffer;
      Writer<StringBuffer> jsonWriter;

      doc.Accept(jsonWriter);

      std::cout << "output json is : " << jsonBuffer.GetString() << endl;
      return 0;
    }

The program goes into segmentation fault when I execute it. I tried executing with GDB, here is the output:

gdb /usr/local/bin/algoLibrary/algoLibrary 
... Reading symbols from
/usr/local/bin/algoLibrary/algoLibrary...done. (gdb) b main Breakpoint 1 at 0x2ad46: file
/home/farouk/Documents/algoEngine/library/sources/main.cc, line 11.
(gdb) r 
Starting program: /usr/local/bin/algoLibrary/algoLibrary 
[Thread debugging using libthread_db enabled] Using host libthread_db
library "/lib/x86_64-linux-gnu/libthread_db.so.1". 
n
Breakpoint 1, main (argc=1, argv=0x7fffffffe468) at
/home/farouk/Documents/algoEngine/library/sources/main.cc:11 11 int main(int argc, char* argv[]) { 
(gdb) n 
28    const char* json =
"{\"address\":\"127.0.0.1\", \"port\":9100}"; 
(gdb)  
29    Document doc; 
(gdb)  
30    doc.Parse(json); 
(gdb)  
32    StringBuffer jsonBuffer;
(gdb)  
33    Writer<StringBuffer> jsonWriter; 
(gdb)  
35   
doc.Accept(jsonWriter); (gdb) 

Program received signal SIGSEGV, Segmentation fault.
0x000055555556e2d0 in
rapidjson::internal::Stack<rapidjson::CrtAllocator>::Reserve<char>
(this=0x0, count=1) at
/usr/local/include/rapidjson/internal/stack.h:118 118           if(RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) (stackEnd_ - stackTop_)))

Solution

  • Ok I finally found my problem by comparing my code line by line with the example in rapidjson/example/serialize/serialize.cpp:

    when instantiating a rapidjson::Writer (or PrettyWritter), you need to call its constructor with the StringBuffer as argument. My code would then become:

        int main(int argc, char* argv[]) {
      const char* json = "{\"address\":\"127.0.0.1\", \"port\":9100}";
      Document doc;
      doc.Parse(json);
    
      StringBuffer jsonBuffer;
      Writer<StringBuffer> jsonWriter(jsonBuffer);  // Update is here: give jsonBuffer to jsonWriter
    
      doc.Accept(jsonWriter);
    
      std::cout << "output json is : " << jsonBuffer.GetString() << endl;
      return 0;
    }