2

This post is related to this one: Segmentation fault during Serialization by using protobuf in C++17

But I have narrowed it down to the specific problem and decided to make separated post.

My goal is to serialize information by using protobuf in C++.

proto file from ./proto folder:

syntax="proto3";

package PhoneBookSerialize;

message Date {
    int32 year = 1;
    int32 month = 2;
    int32 day = 3;
}

message Contact {
    string name = 1;
    Date birthday = 2;
    repeated string phone_number = 3;
}

message ContactList {
    repeated Contact contact = 1;
}

main.cpp in ./src folder

#include "contact.pb.h"
#include <sstream>
#include <iostream>

using namespace std;

int main() {

  // Example 2: Serialize single Date
  PhoneBookSerialize::Date date;
  date.set_year(1990);
  date.set_month(6);
  date.set_day(15);
  
  // Serialize Date
  ostringstream date_output(std::ios::binary);
  date.SerializeToOstream(&date_output);
  std::string serialized_date = date_output.str();
  std::cout << "Serialized date size: " << serialized_date.size() << std::endl;

  // Deserialize Date
  PhoneBookSerialize::Date parsed_date;
  istringstream date_input(serialized_date, std::ios::binary);
  parsed_date.ParseFromIstream(&date_input);
  std::cout << "Deserialized date: " 
            << parsed_date.year() << "-"
            << parsed_date.month() << "-"
            << parsed_date.day() << std::endl;

  std::cout << "================================================" << std::endl;
  // Example 3: Serialize single Contact
  PhoneBookSerialize::Contact contact;
  contact.set_name("John Doe");

  contact.mutable_birthday()->set_year(1990);
  contact.mutable_birthday()->set_month(6);
  contact.mutable_birthday()->set_day(15);
  contact.add_phone_number("+1234567890");
  contact.add_phone_number("+1234567891");

  // Serialize Contact
  ostringstream contact_output(std::ios::binary);
  if (!contact.SerializeToOstream(&contact_output)) {
    std::cerr << "Failed to serialize contact!" << std::endl;
  } else {
    std::cout << "Successfully serialized contact (size: " << contact_output.str().size() << " bytes)" << std::endl;
  }

  std::string serialized_contact = contact_output.str();
  std::cout << "Serialized contact size: " << serialized_contact.size() << std::endl;

  // Deserialize Contact
  PhoneBookSerialize::Contact parsed_contact;
  istringstream contact_input(serialized_contact, std::ios::binary);
  if (!parsed_contact.ParseFromIstream(&contact_input)) {
    std::cerr << "Failed to parse contact!" << std::endl;
  }
  std::cout << "Deserialized contact:" << std::endl
            << "Name: " << parsed_contact.name() << std::endl
            << "Birthday: " 
            << parsed_contact.birthday().year() << "-"
            << parsed_contact.birthday().month() << "-"
            << parsed_contact.birthday().day() << std::endl
            << "Phone number: " << parsed_contact.phone_number(0) << std::endl
            << "Phone number: " << parsed_contact.phone_number(1) << std::endl;


  return 0;
}

CMakeLists.txt file in . folder:

cmake_minimum_required(VERSION 3.20)
project(PhoneBookProtobuf LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Add debug flags
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -fcolor-diagnostics -fansi-escape-codes -fsanitize=address -fsanitize=undefined -DDEBUG -fno-omit-frame-pointer -fno-optimize-sibling-calls -Werror")

# Find Protocol Buffers package
find_package(Protobuf REQUIRED)


# Find Abseil package
find_package(absl REQUIRED)
include_directories(${Protobuf_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})

# Generate protobuf files from proto directory
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS proto/contact.proto)

# Add all source files
add_executable(main
    src/main.cpp
    ${PROTO_SRCS}
    ${PROTO_HDRS}
)

# Link necessary libraries
target_link_libraries(main 
    ${Protobuf_LIBRARIES}
    absl::log
    absl::log_internal_message
    absl::log_internal_check_op
)

# Add include directories
target_include_directories(main PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/src
    ${CMAKE_CURRENT_BINARY_DIR}
    ${Protobuf_INCLUDE_DIRS}
)

after I build (creates a ./build folder) and run the code I am getting the following error message:

 ./build/main                
Serialized date size: 7
Deserialized date: 1990-6-15
================================================
Successfully serialized contact (size: 45 bytes)
Serialized contact size: 45
AddressSanitizer:DEADLYSIGNAL
=================================================================
==76867==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7ff7b890a050 sp 0x7ff7b890a008 T0)
==76867==Hint: pc points to the zero page.
==76867==The signal is caused by a READ memory access.
==76867==Hint: address points to the zero page.
    #0 0x000000000000  (<unknown module>)
    #1 0x000107a3dbdb in bool google::protobuf::internal::MergeFromImpl<false>(google::protobuf::io::ZeroCopyInputStream*, google::protobuf::MessageLite*, google::protobuf::internal::TcParseTableBase const*, google::protobuf::MessageLite::ParseFlags)+0xd1 (libprotobuf.29.3.0.dylib:x86_64+0x10cbdb)
    #2 0x000107a3eda2 in google::protobuf::MessageLite::ParseFromIstream(std::__1::basic_istream<char, std::__1::char_traits<char>>*)+0x32 (libprotobuf.29.3.0.dylib:x86_64+0x10dda2)
    #3 0x000107603cd7 in main main.cpp:57
    #4 0x7ff8165ad52f in start+0xbef (dyld:x86_64+0xfffffffffff1f52f) 

The error is cased by the birthday field of the type Date in the Contact message. For some reason when I use:

  contact.mutable_birthday()->set_year(1990);
  contact.mutable_birthday()->set_month(6);
  contact.mutable_birthday()->set_day(15);

or CopyFrom method it causes a segmentation fault.

  • OS: macOS
  • protoc version: libprotoc 29.3
  • generated files contact.pb.cc and contact.pb.h are in the build folder, if it's important.

Summary:

  1. If I remove Date field from the Contact message (and all the code in main() related to setting Date field), then problem disappears.

  2. When I leave Date field in the Contact message BUT I don't use set methods for this field in main(), then problem dissappears as well.

Basically: problem occurs due to set methods (contact.mutable_birthday()->set_year(1990) etc.)

Why does Date message inside Contact message causes the segmentation fault?

6
  • @DrewDormann I accepted the answer, the new question is more precise in problem description. Commented Apr 16 at 13:56
  • So, if you remove the separate Date serialization/deserialization, or don't set the date of the Contact, the problem disappears? Commented Apr 16 at 15:12
  • @molbdnilo 1. If I remove Date field from the Contact message (and all the code in main() related to setting Date field), then problem disappears. 2. When I leave Date field in the Contact message BUT I don't use set methods for this field in main(), then problem dissappears as well. Basically: problem occurs due to set methods (contact.mutable_birthday()->set_year(1990) etc.) Commented Apr 16 at 15:17
  • @DaniilYefimov The first point referred to the code commented as "Example 2". If this is a minimal reproducible example, the problem would persist if you removed it, so does it? Commented Apr 16 at 15:25
  • @molbdnilo If I completely remove Example 2 (only Example 3 is left), then no, problem still remains. Commented Apr 16 at 16:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.