Segfault Возникает при использовании соединителя MariaDB c и регулярного выражения

#c #segmentation-fault #mariadb #connector

Вопрос:

Я создаю простую служебную программу, которая запрашивает базу данных mysql и использует регулярные выражения для выделения строк в табличных данных.

Я использую MariaDB c /connector и последние версии MariaDB. Код был скопирован с веб-сайта MariaDB. Я упростил программное обеспечение, чтобы проиллюстрировать проблему. Смотреть ниже:

 // g   -o mariadb_connect mariadb_connect.cpp -lmariadbcpp
// From https://mariadb.com/docs/clients/connector-cpp/
// with three additional lines that cause segfault

#include <iostream>
#include <mariadb/conncpp.hpp>

#include <regex>    // <-- Added to the example

int main()
{
   try
   {
      // Instantiate Driver
      sql::Driver* driver = sql::mariadb::get_driver_instance();

      // Configure Connection
      // The URL or TCP connection string format is
      // ``jdbc:mariadb://host:port/database``.
      sql::SQLString url("jdbc:mariadb://localhost:3306/??????");

      // Use a properties map for the user name and password
      sql::Properties properties({
            {"user", "???????"},
            {"password", "????????"}
         });

      // Establish Connection
      // Use a smart pointer for extra safety
      std::unique_ptr<sql::Connection> conn(driver->connect(url, properties));

      // Use Connection
      std::cout << "Using the connection" << std::endl; // <-- Added

      std::regex regexp("(faststatic.com)(.*)");    // <-- Added (Causes segfault)

      // Close Connection
      conn->close();
   }

   // Catch Exceptions
   catch (sql::SQLExceptionamp; e)
   {
      std::cout << "Error Connecting to MariaDB Platform: "
         << e.what() << std::endl;

      // Exit (Failed)
      return 1;
   }

   // Exit (Success)
   return 0;
}
 

(???? используется для личных данных)

Скомпилирован с помощью g на экземпляре AWS EC2 под управлением Amazon Linux 2 AMI.

Отлично компилируется и работает нормально, пока я не добавил строку регулярного выражения std::regex (…). Он по-прежнему отлично компилируется с добавлением, но при выполнении вызывает segfault.

Я использовал gdb, который обеспечивает следующий вывод с точкой останова, установленной в main.

 (gdb) b main
Breakpoint 1 at 0x40404b: file mariadb_connect.cpp, line 15.
(gdb) run
Starting program: /home/msellers/proj/preload_images/spike/mariadb_connect
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x000000000064a588 in ?? ()
 

Вот вывод команды gdb bt после segfault:

 (gdb) bt
#0  0x000000000064a588 in ?? ()
#1  0x0000000000409155 in std::__detail::_Scanner<char>::_M_scan_normal (this=0x7fffffffe018) at /usr/include/c  /7/bits/regex_scanner.tcc:119
#2  0x00000000004084a1 in std::__detail::_Scanner<char>::_M_advance (this=0x7fffffffe018) at /usr/include/c  /7/bits/regex_scanner.tcc:80
#3  0x00007ffff7c3e060 in std::__detail::_Compiler<std::regex_traits<char> >::_M_match_token (this=this@entry=0x7fffffffe000, token=std::__detail::_ScannerBase::_S_token_subexpr_begin) at /usr/local/include/c  /4.9.4/bits/regex_compiler.tcc:541
#4  0x00007ffff7c513a2 in std::__detail::_Compiler<std::regex_traits<char> >::_M_match_token (token=std::__detail::_ScannerBase::_S_token_subexpr_begin, this=0x7fffffffe000) at /usr/local/include/c  /4.9.4/bits/regex_compiler.tcc:316
#5  std::__detail::_Compiler<std::regex_traits<char> >::_M_atom (this=this@entry=0x7fffffffe000) at /usr/local/include/c  /4.9.4/bits/regex_compiler.tcc:326
#6  0x00007ffff7c515b0 in std::__detail::_Compiler<std::regex_traits<char> >::_M_term (this=0x7fffffffe000) at /usr/local/include/c  /4.9.4/bits/regex_compiler.tcc:136
#7  std::__detail::_Compiler<std::regex_traits<char> >::_M_alternative (this=0x7fffffffe000) at /usr/local/include/c  /4.9.4/bits/regex_compiler.tcc:118
#8  0x00007ffff7c51809 in std::__detail::_Compiler<std::regex_traits<char> >::_M_disjunction (this=this@entry=0x7fffffffe000) at /usr/local/include/c  /4.9.4/bits/regex_compiler.tcc:97
#9  0x00007ffff7c51e18 in std::__detail::_Compiler<std::regex_traits<char> >::_Compiler (this=0x7fffffffe000, __b=<optimized out>, __e=<optimized out>, __traits=..., __flags=<optimized out>)
    at /usr/local/include/c  /4.9.4/bits/regex_compiler.tcc:82
#10 0x00007ffff7c5222d in std::__detail::__compile_nfa<std::regex_traits<char> > (__first=<optimized out>, __last=<optimized out>, __traits=..., __flags=<optimized out>) at /usr/local/include/c  /4.9.4/bits/regex_compiler.h:158
#11 0x00007ffff7c524da in std::basic_regex<char, std::regex_traits<char> >::basic_regex<char const*> (__f=<optimized out>, __last=<optimized out>, __first=<optimized out>, this=0x7ffff7dc2a40 <sql::mariadb::UrlParser::URL_PARAMETER>)
    at /usr/local/include/c  /4.9.4/bits/regex.h:540
#12 std::basic_regex<char, std::regex_traits<char> >::basic_regex (this=0x7ffff7dc2a40 <sql::mariadb::UrlParser::URL_PARAMETER>, __p=<optimized out>, __f=<optimized out>) at /usr/local/include/c  /4.9.4/bits/regex.h:452
#13 0x00007ffff7c331ee in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/buildbot/src/src/UrlParser.cpp:34
#14 _GLOBAL__sub_I_UrlParser.cpp(void) () at /home/buildbot/src/src/UrlParser.cpp:444
#15 0x00007ffff7de7dc2 in call_init (l=<optimized out>, argc=argc@entry=1, argv=argv@entry=0x7fffffffe2b8, env=env@entry=0x7fffffffe2c8) at dl-init.c:72
#16 0x00007ffff7de7eb6 in call_init (env=0x7fffffffe2c8, argv=0x7fffffffe2b8, argc=1, l=<optimized out>) at dl-init.c:119
#17 _dl_init (main_map=0x7ffff7ffe130, argc=1, argv=0x7fffffffe2b8, env=0x7fffffffe2c8) at dl-init.c:120
#18 0x00007ffff7dd9f2a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#19 0x0000000000000001 in ?? ()
#20 0x00007fffffffe520 in ?? ()
#21 0x0000000000000000 in ?? ()
(gdb)
 

Помогает ли это?

Марк

Комментарии:

1. Показать bt вывод.

2. Я только что проверил документы mariadb, и в его примере для компиляции кода он добавляет -std=c 11 , чтобы скомпилировать его для C 11. попробуй и посмотри, не изменится ли что-нибудь.

3. Скомпилирован с помощью-std=c 11 — та же проблема. Спасибо за комментарий.

4. Какая версия компилятора?

5. Версия GCC 7.3.1

Ответ №1:

Версия GCC 7.3.1

На обратном пути мы видим, что сбой происходит в реализации регулярных выражений GCC-7:

 #1  0x0000000000409155 in std::__detail::_Scanner<char>::_M_scan_normal (this=0x7fffffffe018) at /usr/include/c  /7/bits/regex_scanner.tcc:119
 

Мы также видим, что этот сбой происходит в то время как некоторые глобальные внутри (предположительно 1) Соединитель MariaDB инициализируется при использовании версии GCC-4.9.4 libstdc :

 #12 std::basic_regex<char, std::regex_traits<char> >::basic_regex (this=0x7ffff7dc2a40 <sql::mariadb::UrlParser::URL_PARAMETER>, __p=<optimized out>, __f=<optimized out>) at /usr/local/include/c  /4.9.4/bits/regex.h:452
#13 0x00007ffff7c331ee in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/buildbot/src/src/UrlParser.cpp:34
 

Весьма вероятно, что это несоответствие 4.9.4 и 7.3.1 является причиной сбоя, и что либо создание приложения с помощью g -4.9.4, либо создание MariaDB с помощью g -7.3.1 устранит проблему.

Теоретически версия GCC libstdc должна быть обратно совместимой, но проверить совместимость с ABI C довольно сложно, и было сделано много ошибок. Кроме того, g 4.9.4 является древним.

Другим возможным решением является создание приложения с clang использованием libc -это позволит избежать любой возможности конфликтов символов 2.


1 Вы можете проверить, действительно ли кадр #13 поступает из MariaDB, выполнив следующие команды GDB: frame 13 , info symbol $pc .

2 Для достижения этой цели вам, возможно , потребуется явно указать clang использовать libc , так как по умолчанию может использоваться libstdc . Используйте clang -stdlib=libc ... , чтобы быть уверенным. Документация здесь.

Комментарии:

1. Спасибо за предложение. Я скомпилировал MariaDB c /connector с gcc 7.3.1, и он отлично работает!

2. @Маркс. Рад, что это сработало. Этот ответ был невозможен без вывода обратной трассировки-поэтому, пожалуйста, предоставьте его (или другую соответствующую информацию) в будущих вопросах без запроса-детали имеют значение !