Сбой Protobuf ShortDebugString()

У меня есть следующий прототип:

syntax = "proto3";
package pb;

message FooBar {
  string foo = 1;
  string bar = 2;
}

message FooBarList {
  repeated FooBar foobar = 1;
}

Я просто заполняю повторяющийся список двумя значениями и пытаюсь распечатать его, как показано ниже:

#include <iostream>
#include "foobar.pb.h"

int main()
{
    pb::FooBarList foobar_list;

    auto foobar1 = foobar_list.add_foobar();
    foobar1->set_foo("foo1");
    foobar1->set_bar("bar1");

    auto foobar2 = foobar_list.add_foobar();
    foobar2->set_foo("foo2");
    foobar2->set_bar("bar2");

    try {
        std::cout << foobar_list.ShortDebugString() << std::endl;
    }
    catch (const std::exception& e) {
        std::cout << "error: " << e.what() << std::endl;
        return -1;
    }

    return 0;
}

Это генерирует следующий вывод:

error: Unknown error -1

Таким образом, ShortDebugString() запускает исключение в строке, которая не содержит никакой значимой информации.
Я делаю что-то не так или мне нужно как-то инициировать сериализацию перед вызовом ShortDebugString()?

Вот gdb callstack, если я позволю исключению распространяться:

Program received signal SIGABRT, Aborted.
0x00007ffff7add355 in raise () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff7add355 in raise () from /usr/lib/libc.so.6
#1  0x00007ffff7ac6853 in abort () from /usr/lib/libc.so.6
#2  0x00007ffff7e5d86a in __gnu_cxx::__verbose_terminate_handler () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/vterminate.cc:95
#3  0x00007ffff7e69d8a in __cxxabiv1::__terminate (handler=<optimized out>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:48
#4  0x00007ffff7e69df7 in std::terminate () at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:58
#5  0x00007ffff7e6a09e in __cxxabiv1::__cxa_throw (obj=obj@entry=0x5555556e1550, 
    tinfo=tinfo@entry=0x7ffff7f97590 <typeinfo for std::system_error>, dest=dest@entry=0x7ffff7e96860 <std::system_error::~system_error()>)
    at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:95
#6  0x00007ffff7e609bc in std::__throw_system_error (__i=-1)
    at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/ext/new_allocator.h:89
#7  0x00005555555a1018 in google::protobuf::internal::AssignDescriptors(google::protobuf::internal::DescriptorTable const*, bool) ()
#8  0x000055555556e77f in pb::FooBarList::GetMetadataStatic() ()
#9  0x000055555556ceb9 in pb::FooBarList::GetMetadata() const ()
#10 0x00005555555d1fb4 in google::protobuf::TextFormat::Printer::Print(google::protobuf::Message const&, google::protobuf::TextFormat::Printer::TextGenerator*) const ()
#11 0x00005555555d3ef9 in google::protobuf::Message::ShortDebugString[abi:cxx11]() const ()
#12 0x00005555555705ac in main ()
(gdb) 

ИЗМЕНИТЬ

Вот CMakeLists.txt, использованный для создания этого проекта:

cmake_minimum_required(VERSION 3.10)
project(proto-foobar)

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

set(Protobuf_USE_STATIC_LIBS ON)
find_package(Protobuf MODULE REQUIRED)

set(PROTO_DEFINITIONS_PATH "${CMAKE_SOURCE_DIR}/protos")
set(PROTO_DEFINITIONS "${PROTO_DEFINITIONS_PATH}/*.proto")
set(PROTO_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/source")
file(MAKE_DIRECTORY ${PROTO_OUTPUT_PATH})

set(PROTO_HEADERS "${PROTO_OUTPUT_PATH}/foobar.pb.h")
set(PROTO_SOURCES "${PROTO_OUTPUT_PATH}/foobar.pb.cc")

add_custom_command(OUTPUT ${PROTO_HEADERS} ${PROTO_SOURCES}
                   COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
                   ARGS --cpp_out=${PROTO_OUTPUT_PATH} 
                        --proto_path=${PROTO_DEFINITIONS_PATH} 
                        ${PROTO_DEFINITIONS}
                   DEPENDS ${PROTO_DEFINITIONS}
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                   COMMENT "Compiling ${PROJECT_NAME} protos")    

file(GLOB_RECURSE PROJECT_FILES "${CMAKE_SOURCE_DIR}/source/*.cpp")
add_executable(${PROJECT_NAME} ${PROTO_SOURCES} ${PROJECT_FILES})

target_link_libraries(${PROJECT_NAME}       PUBLIC ${PROTOBUF_LIBRARY})
target_include_directories(${PROJECT_NAME}  PUBLIC ${PROTO_OUTPUT_PATH})

Вот дерево проекта:

├── CMakeLists.txt
├── protos
│   └── foobar.proto
└── source
    ├── foobar.pb.cc
    ├── foobar.pb.h
    └── main.cpp

person codentary    schedule 05.06.2020    source источник
comment
Работает нормально. Выход: foobar { foo: "foo1" bar: "bar1" } foobar { foo: "foo2" bar: "bar2" }. Как вы скомпилировали? Команда?   -  person Azeem    schedule 06.06.2020
comment
@Azeem, я добавил к вопросу больше деталей.   -  person codentary    schedule 08.06.2020
comment
Вы тестировали его, кроме CMake?   -  person Azeem    schedule 08.06.2020
comment
@Azeem, в частности, в этом примере проекта нет. Дело в том, что я использую такой же cmake в каком-то другом проекте, и он отлично работает. Сначала я сделал этот пример, чтобы продемонстрировать какую-то другую проблему, но потом я получил это, когда пытался распечатать для отладки.   -  person codentary    schedule 11.06.2020
comment
Верно. Вы можете проверить это без cmake, чтобы увидеть, работает ли это. В этом случае могут возникнуть проблемы с конфигурацией. В противном случае проблема может быть связана со средой выполнения.   -  person Azeem    schedule 11.06.2020


Ответы (1)


(У меня была точно такая же проблема, и я немного покопался в ней.)

Триггером в данном случае является эта часть кода . Он содержит (косвенно) вызов std::call_once, который в Linux реализован с использованием pthread_once. Это, в свою очередь, требует, чтобы ваш двоичный файл был связан с библиотекой pthread (т. е. для этого требуется флаг компоновщика -lpthread).

Если ваш двоичный файл не был связан с pthread, вы получите ошибку, которую вы видели, как указано здесь вместе с рецептом исправления этого .

person thkala    schedule 14.07.2020
comment
Спасибо! В дополнение к -lpthread мне также нужен был флаг -pthread, чтобы исправить мой сбой. Более подробная информация также здесь: github.com/protocolbuffers/protobuf/issues/4958 (Примечание : я использовал protobuf 3.9.2 и gcc 9.3.0) - person arr_sea; 11.09.2020