Я сейчас пытаюсь создать программу на C ++ для Linux, которая использует udev для мониторинга новых устройств ввода и запускает программу после ее подключения. Однако всякий раз, когда я подключаю свой контроллер Xbox 360 (который распознает мой linux box) в качестве устройства ввода. Не «hidraw».) Я получаю эту ошибку:
прекращение вызова после создания экземпляра ‘std :: logic_error’
what (): basic_string :: _ M_construct null недействительно
Прервано (ядро сброшено)
Это сообщение об ошибке сопровождается кодом ошибки 134. Я искал все выше и ниже по сетям, чтобы попытаться найти решение. Я обнаружил, что некоторые сайты говорят о «свисающих ссылках», которые я проверил, и не нашел ни одного (хотя я не самый наблюдательный, поэтому, если я ошибаюсь, скажите мне).
Я смог сузить ошибку до scanner()
функция, вероятно, где-то в области if (ret > 0 && FD_ISSET(fd, &fds))
Мой код:
#include <iostream>
#include <libudev.h>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <unistd.h>
#include <cstdlib>
#include <fstream>
#include <sys/types.h>
#include <pwd.h>
using namespace std;
//for error reporting to the log file at ~/.xboxdrv/LOGFILE.txt
int error(std::string out)
{
int SENT = 1;
while ( SENT == 1)
{
std::string home = getenv("HOME");
if (home.empty())
{
home = getpwuid(getuid())->pw_dir;
}
ofstream errout ((home + "/.xboxdrv/LOGFILE.txt").c_str(), ios::out | ios::app);
if (errout.is_open())
{
errout << out << std::endl;
SENT = 0;
}
else continue;
errout.close();
}
//check file size, if > ~30MB, compress into a zip
return 0;
}
//check newly mounted USB device for standard support
int check_standard(std::string check)
{
int success = std::system( ("python3 /etc/usb-scanner/check_support_standard.py " + check).c_str() );
if (success == 1)
{
std::cout << 0;
}
else
{
std::cout << 1;
}
return 0;
}
//check newly mounted USB for non-standard
int check_non_standard(std::string check)
{
int success = std::system( ("python3 /etc/usb-scanner/check_support_nonstandard.py " + check).c_str() );
if (success == 1)
{
std::cout << 0;
}
else
{
std::cout << 1;
}
return 0;
}
//LISTEN for newly mounted USB devices
int scanner()
{
cout << "Start Scanner(). . . ";
struct udev *udev;
struct udev_device *dev;
struct udev_monitor *mon;
int fd;
//Create the udev object
udev = udev_new();
if (!udev)
{
error("ERROR: Can't create new udev object");
cout << "Can't create udev";
return 1;
}
//Set up a monitor to monitor input devices
cout << "Starting monitor. . . ";
mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL);
udev_monitor_enable_receiving(mon);
/* Get the file descriptor (fd) for the monitor.
This fd will get passed to select() */
fd = udev_monitor_get_fd(mon);
int SENT = 1;
cout << "Starting while 2. . . ";
while (SENT == 1)
{
/* Set up the call to select(). In this case, select() will
only operate on a single file descriptor, the one
associated with our udev_monitor. Note that the timeval
object is set to 0, which will cause select() to not
block. */
fd_set fds;
struct timeval tv;
int ret;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 0;
ret = select(fd+1, &fds, NULL, NULL, &tv);
cout << ret;
//Check if our file descriptor has received data.
if (ret > 0 && FD_ISSET(fd, &fds))
{
/* Make the call to receive the device.
select() ensured that this will not block. */
dev = udev_monitor_receive_device(mon);
if (dev)
{
error("NOTICE: Got Device");
std::string action = udev_device_get_action(dev);
std::string v = udev_device_get_sysattr_value(dev,"idVendor");
std::string p = udev_device_get_sysattr_value(dev,"idProduct");
std::string vpid = (v + ":" + p).c_str();
if (action == "add")
{
SENT = 0;
}
udev_device_unref(dev);
std::cout << vpid;
}
else
{
error("ERROR: No Device from receive_device().");
cout << "ERROR: No Device from receive_device().";
}
}
usleep(100000);
fflush(stdout);
}
udev_unref(udev);
return 0;
}
//main function
int main ()
{
cout << "Start. . . ";
int SENT = 1;
while (SENT == 1)
{
cout << "Start While 1. . . ";
string new_usb;
new_usb = scanner();
cout << new_usb;
int stand_sup = check_standard(new_usb);
if (stand_sup == 1)
{
int non_stand_sup = check_non_standard(new_usb);
if (non_stand_sup == 0)
{
int pid = fork();
if (pid == 0)
{
execl("bash", "/etc/usb-scanner/unsupported.sh", new_usb, (char *) 0);
}
}
}
else if (stand_sup == 0)
{
int pid = fork();
if (pid == 0)
{
execl("bash", "/etc/usb-scanner/supported.sh", (char *) 0);
}
}
}
}
Просто последнее замечание: все cout
материал, который будет просто выводиться на консоль, будет удален, когда я на самом деле использую это. Это просто для целей отладки, и мне лень его вынимать, прежде чем я надену его здесь.
Спасибо за любую помощь!
РЕДАКТИРОВАТЬ
После прохождения gdb
Я нашел строки ошибок 145 и 146 (где я бегу udev_device_get_sysattr_value
для того, чтобы получить поставщика и идентификаторы продукта). Я посмотрел вокруг, чтобы увидеть, есть ли какая-либо документация, детализирующая, какие данные мне нужны для передачи этой функции, но все просто говорит, что это должно быть udev_device
структура и const char
, но, исходя из этого, переменная dev и строки, которые я передаю, должны работать. Помимо этих данных и того, какие данные он возвращает, я не могу найти больше информации об этой функции.
Я чувствую, что возвращение из udev_monitor_receive_device(mon)
который был сохранен в dev выше, не совсем соответствует информации, которая udev_device_get_sysattr_value
необходимо для того, чтобы правильно работать.
Как получить правильную информацию для передачи этой функции, вызывающей эту ошибку? Если это не проблема, есть ли другой способ получить идентификатор поставщика / продукта в C ++?
Задача ещё не решена.
Других решений пока нет …