LINUX.ORG.RU

342
Всего сообщений: 4616

AddressSanitizer GCC + custom halt

Всем привет,

Вопрос такой, допустим имеется многопоточная программка, в которой срабатывает ASan, завершая процесс с выводом ошибки.

Могу ли я внедриться в это событие и вызвать собственную функцию, которая бы могла допустим из контекста текущего потока получить интересуемую информацию и добавить ее в вывод санитайзера до того как процесс грохнется?

 

sotlef ()

ищется pjsip media android dev на разовый проект

Ищется android разработчик для интеграции проброса звука («зарулить media») из pjsip android (возможны любые ваши варианты из опенсорса) в <> android приложение (возможны варианты с kaios \ win приложениями на ваш выбор)

Бюджет определяет разработчик, сроки не ограничены.

Есть пример того как это может выглядеть, есть понимание как это примерно можно сделать, есть мощностя для быстрой сборки.

Подробности, связь — pjsipmediadev@gmail.com

 , , , ,

smilessss ()

Возможна ли в C++ compile-time интроспекция?

Суть такова: со стороны передается некий объект. Могу ли я определить его тип и получить доступ к его структуре до исполнения программы? В нынешних стандартах что-то предусмотрено для этого? Может быть, сторонние библиотеки?

Всем спасибо.

 , интроспекция

LongLiveUbuntu ()

Где делать универсальную сборку

Привет, ЛОР.

Приходилось сталкиваться с мнением, что наилучший способ получить универсальный бинарник под линуксом — это собирать проект под в меру стареньким дистрибутивом и соответственно, со стареньким glibc.

Какой дистрибутив для этого лучше взять в 2023 году? Debian Oldstable (который сейчас Buster) подойдёт?

 ,

hobbit ()

Быстрый фикс для неожиданного поведения программы на С++

Есть QuiteRSS, в котором есть баг: при сворачивании его в systray он записывает базу на диск, хотя не должен:

https://github.com/QuiteRSS/quiterss/issues/1578

Пытался сам исправить - не получилось, я в C++ не шарю.

 , ,

tempuser003 ()

Подскажите подходящий алгоритм сжатия

Вопрос к тем, кто интересуется алгоритмами сжатия без потерь, может можете подсказать?

В программе имеется utf8-символьный массив (на самом деле их много таких массивов), в котором последовательно размещены строки: количество байт строки, потом содержимое строки, снова количество байт строки, содержимое строки и т.д. Хотелось бы этот массив ужать каким-нибудь известным алгоритмом так, чтобы при необходимости я мог зная индекс начала строки разархивировать только ее. Строки короткие, в среднем где-то до 300 символов. Строки в основном осмысленный текст на русском, либо коды на латинице (шаблонные, как правило очень короткие до 10 символов).

Интересует в первую очередь название какого-нибудь уже известного алгоритма.

 ,

sotlef ()

CPS в нефункциональных ЯП

Вопрос тем, кто использует (изначально, преимущественно) не функциональные ЯП (C++, Java, Python). Как вы относитесь к CPS (Continuation-Passing Style)?

Для тех, кто не в курсе, например, есть некая операция, которая может завершиться удачно, а может с ошибкой, и вместо:

Result performOperation()
{
	return doOperation();
}

...

Result result = performOperation();

if (OK == result)
{
	std::cout << "OK" << std::endl;
}
else
{
	std::cout << "NOK" << std::endl;
}

Делается так:

void performOperation(Func onSuccess, Func onFailure)
{
	if (OK == doOperation())
	{
		onSuccess();
	}
	else
	{
		onFailure();
	}
}

...

performOperation([]() {
			std::cout << "OK" << std::endl;
		},
	         []() {
			std::cout << "NOK" << std::endl;
		});

Заранее пардон, если какие-то синтаксические ошибки, это чисто концептуальные примеры.

Даже предлагаю варианты ответов:

  1. Код с этими лямбдами сложно понимать, всегда объявляю все функции и методы по-старинке, вызываю явно в императивном стиле;

  2. Да, только так и делаю. Умные люди придумали ФП не просто так и гораздо нагляднее, не то, что у дурачков с императивной лапшой;

  3. Мне всё равно, могу/делаю и так, и сяк.

 ,

seiken ()

C++ Как собрать самостоятельный пакет?

Часто бывает, что скомпилировав бихарник на c++ в linux arch, юзеры не могут его запустить на какой-нибудь юбунте, так как им нужна новая версия libc и докачать ещё всяких зависимостей… Короч, как собрать прогу чтобы у всех пошло? Может стоит слинковать всё в один бинарь или сделать какой-то пакет для установки в специальном формате? А если распространять через исходники, то зависимости тоже хранить с кодом? Используется git и система сборки SCons, под виндой все зависимости собраны в .dll и коды выкачаны в папку thirdparty, под линуксом зависимости скачаны в виде dev пакетов через pacman и мне всегда приходится писать инструкцию чтобы юзеры качали себе такие же зависимости самостоятельно.

Компиляторы: clang/mingw/gcc
Зависимости: openmp, openal, c++20, glfw3

 , ,

HPW-dev ()

Либу на С/C++ на анализ движения?

Посоветуйте, пожалста???

Есть мжпег камера, делаю с нее снимки ffmpeg либой, но хотелось бы иметь возможность проанализировать дельту движа между кадрами, в тупую сравнить по размеру кадры выходит не очень.

 ,

wolverin ()

V4L2: ошибка удаления буфера из очереди: недопустимый аргумент

Я написал сервер, который постоянно захватывает видеокадры, и накапливает их в буфере (видео идет 5 секунд, оно постоянно обновляется), как только клиент подключается к серверу, это видео передается через сокет.

У меня проблема. Ошибка «Ошибка удаления буфера из очереди: недопустимый аргумент» в строке «if (ioctl (fd, VIDIOC_DQBUF, &buf) == -1)» Что я делаю неправильно?

    #include <unistd.h>
    #include <thread>
    #include <mutex>
    #include <deque>
    #include <stdio.h>
    #include <stdlib.h>
    #include <cstdlib>
    #include <string.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <sys/time.h>
    #include <sys/mman.h>
    #include <linux/videodev2.h>
    #include <math.h>
    #include <typeinfo>
    #include <iostream>
    #include <pthread.h>
    #include <linux/i2c.h>
    #include <sys/ioctl.h>
    
    
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <cstring> // memset()
    
    #include <cstring>
    #include <vector>
    
    #include <opencv2/opencv.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/core.hpp>
    #include "opencv2/imgproc.hpp"
    #include <opencv2/imgcodecs.hpp>
    #include <opencv2/core/mat.hpp>
    #include <opencv2/videoio.hpp>
    
    
    
    
    extern "C" {
        #include <linux/i2c-dev.h>
        #include "i2c/smbus.h"
    }
    
    #define CLEAR(x) memset(&(x), 0, sizeof(x))//очистка
    #define   WIDTH   1920                       // The width of the picture
    #define   HEIGHT  1080                       // The height of the picture
    #define   FMT     V4L2_PIX_FMT_BGR24 // формат поддерживаемый матрицей
    #define mydelay usleep (1000)// минимальная возможная задержка шага 100 мкс
    #define pwmmydelay usleep (1000) // задержка между шагами
    #define I2C4_PATH "/dev/i2c-3"
    #define I2C2_PATH "/dev/i2c-1"
    const unsigned default_port = 3425; // порт, по которому будет стучаться клиент
    const int number_of_seconds = 5;   // кол-во секунд, что сервер будет хранить в памяти
    #define INPUT_ADDR 0x22
    #define INPUT_REG_P0 0x04
    #define dev_name "/dev/video0"
    const double default_fps = 25;      // должно совпадать с таким же значением из client.cpp
    cv::VideoWriter writer;
    using namespace cv;
    using namespace std;
    int grows = 1920; // высота
    int gcols = 1080; // и ширина текущего видео захвата
    deque<Mat> q;  // очередь с кадрами
    mutex qmutex;  // мьютекс для охраны очереди
    int working = 0;
    //структура для получения кадра
           struct buffer {
                   void   *start;
                   int64_t length;
    
           };
    
    /*char*                  	BUFIMAGEA = new char [WIDTH*HEIGHT];
           char*                    	BUFIMAGER = new char [WIDTH*HEIGHT];
           char*                    	BUFIMAGEG = new char [WIDTH*HEIGHT];
           char*                    	BUFIMAGEB = new char [WIDTH*HEIGHT];
           char*                    	BUFIMAGEY = new char [WIDTH*HEIGHT];*/
    
    
           v4l2_format			fmt; // формат видео
           v4l2_buffer              	buf; //
           v4l2_requestbuffers      	req; //
           v4l2_capability          	device_params; //параметры видеомодуля
           v4l2_buf_type            	type;
           fd_set                   	fds;
           timeval                  	tv;
    
           int				r, fd = -1;
    
           unsigned int			i, n_buffers;
    
           buffer*			buffers;
    
           char*				val = (char*)malloc(sizeof(char)*1*WIDTH*HEIGHT);
    
    
    
           using namespace cv;
           using namespace std;
    
    
           static void xioctl(int fh, int request, void *arg)//настройка параметров камеры
           {
                   int r;
    
                   do {
                           r = ioctl(fh, request, arg);
                   } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
    
                   if (r == -1) {
                           fprintf(stderr, "error %d, %s\\n", errno, strerror(errno), request);
                           exit(EXIT_FAILURE);
                   }
           }
    
    
           // структура для получения значения из потока с плавающей запятой
           typedef struct someArgs_tag {
               int id;
               const char *msg;
               double out[2];
           } someArgs_t;
    
    
    
    
    
    
    
    
    
           // тред, в котором идет накопление захваченных кадров в памяти
           void video_grabber_thread() {
               cout << "[VIDEO_GRABBER] : start" << endl;
    
               // очищаем очередь перед началом работы
               {
                   lock_guard<mutex> lk(qmutex);
                   q.clear();
               }
    
               printf("BEGIN\n");
    
                       fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);//открытие камеры
    
                       if (fd < 0) {
                               perror("Cannot open device");
                               exit(EXIT_FAILURE);
                       }
    
                       CLEAR(device_params);
    
                       if (ioctl(fd, VIDIOC_QUERYCAP, &device_params) == -1)// получение параметров видеомодуля из драйвера
                       {
                         printf ("\"VIDIOC_QUERYCAP\" error %d, %s\n", errno, strerror(errno));
                         exit(EXIT_FAILURE);
                       }
    
                       CLEAR(fmt);
    
               //настройка формата
                       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                       fmt.fmt.pix.width       = WIDTH;
                       fmt.fmt.pix.height      = HEIGHT;
                       fmt.fmt.pix.pixelformat = FMT;
                       fmt.fmt.pix.field       = V4L2_FIELD_NONE;
                       xioctl(fd, VIDIOC_S_FMT, &fmt);
                       if (fmt.fmt.pix.pixelformat != FMT) {
                               printf("Libv4l didn't accept ЭТОТ format. Can't proceed.\\n");
                               exit(EXIT_FAILURE);
                       }
    
                       CLEAR(req);//очистка структуры запросов
    
                       req.count = 4;//количество буферов
                       req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                       req.memory = V4L2_MEMORY_MMAP;
                       xioctl(fd, VIDIOC_REQBUFS, &req);
    
                       buffers =(buffer*)calloc(req.count, sizeof(*buffers));//выделение памяти под буферы
                       printf("buffers\n");
                       for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {//подготовка буферов к захвату
                               CLEAR(buf);
    
                               buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                               buf.memory      = V4L2_MEMORY_MMAP;
                               buf.index       = n_buffers;
    
                               xioctl(fd, VIDIOC_QUERYBUF, &buf);
    
                               buffers[n_buffers].length = buf.length;
                               buffers[n_buffers].start = mmap(NULL, buf.length,
                                             PROT_READ | PROT_WRITE, MAP_SHARED,
                                             fd, buf.m.offset);
                               if (MAP_FAILED == buffers[n_buffers].start) {
                                       printf("MAP fail. Can't proceed.\\n");perror("mmap");
                                       printf("MAP fail. Can't proceed.\\n");
                                       exit(EXIT_FAILURE);
                               }
    
                       }
    
               	printf("cycle\n");
                       for (i = 0; i < n_buffers ; ++i) {// поставка буферов в очередь на захват кадров
                               CLEAR(buf);
               		printf("qbuf\n");
                               buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                               buf.memory = V4L2_MEMORY_MMAP;
                               buf.index = i;
                               xioctl(fd, VIDIOC_QBUF, &buf);
                       }
    
               	printf("on\n");
                       type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                       printf("V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
                       ioctl(fd, VIDIOC_STREAMON, &type);
    cout<<"streamon on "<<endl;
    
                       printf("endon\n");
    
               i=0;
               	Mat frame(HEIGHT, WIDTH, CV_8UC1);
    
               	VideoWriter writer("outpu517.avi", VideoWriter::fourcc('H','2','6','4'), 25, Size(WIDTH, HEIGHT), true);//открытие файла для записи
               	if (!writer.isOpened()) {
               	         std::cerr << "Failed to open output file" << std::endl;
               	         return;
               	            }
    
    cout << "124"<<endl;
               		while (working)  { //цикл записи видео в файл
    
                               do {
                                       FD_ZERO(&fds);
                                       FD_SET(fd, &fds);
    
                                       // задаем время ожидания доступности буфера
                                       tv.tv_sec = 2;
                                       tv.tv_usec = 0;//100
    
                                       // проверяем доступность буфера
                                       r = select(fd + 1, &fds, NULL, NULL, &tv);//проверка доступности буфера
                               } while ((r == -1 && (errno = EINTR)));
                               if (r == -1) {
                                       perror("select");
                                       return;
                               }
    
                               // захватываем мьютекс, охраняющий очередь с кадрами
                                              if (!qmutex.try_lock()) {
                                                  this_thread::sleep_for(50ms);
                                              }
    
                                              // удаляем "старые" кадры
                                              while (q.size() >= number_of_seconds * default_fps) {
                                                  q.pop_back();
                                              }
    
               i++;
               cout<<"KADR: "<< i << endl;
                               CLEAR(buf);//макрос для очистки структуры buf от мусора и установки всех ее полей в 0.
                               printf("dqbuf\n");
                               buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                               buf.memory = V4L2_MEMORY_MMAP;//установка способа доступа к буферу
    
                               if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) {
    
                                   if (errno == EAGAIN || errno == EIO) {
                                       // Возможно, буфер еще не готов или возникла ошибка ввода-вывода.
                                       // В этом случае пропустим итерацию и продолжим цикл.
                                       continue;
                                   } else {
                                       perror("Error dequeuing buffer");
                                       return;
                                   }
                               }
                                  printf("memcpy\n");
                                   memcpy(val, buffers[buf.index].start, sizeof(char)*WIDTH*HEIGHT);//копирование содержимого буфера, на который указывает buf.index, в память по указателю val
                                   printf("memcpy proshel \n");
    
                       printf("zapis poshla\n");
    
                       cv::Mat frame(HEIGHT, WIDTH, CV_8UC1, val);
                       cv::Mat framer;
                       cv::cvtColor(frame, framer, cv::COLOR_BayerRG2BGR);
                       writer.write(framer);
    
                       // выводим значения пикселей кадра
                                                             for (int i = 0; i < frame.rows; i++) {
                                                                 for (int j = 0; j < frame.cols; j++) {
                                                                     Vec3b pixel = frame.at<Vec3b>(i, j);
                                                                     cout << "Pixel (" << i << ", " << j << "): ";
                                                                     cout << "B = " << static_cast<int>(pixel[0]) << ", ";
                                                                     cout << "G = " << static_cast<int>(pixel[1]) << ", ";
                                                                     cout << "R = " << static_cast<int>(pixel[2]) << endl;
                                                                 }
                                                             }
    
    
                       if (framer.empty()) {//проверка на пустоту файла
                                   cerr << "ERROR! blank frame grabbed\n";
                                   break;
                               }
    
                       if (ioctl(fd, VIDIOC_QBUF, &buf)==-1){// Помещаем буфер обратно в очередь захвата
                                   	   perror("Error dequeuing buffer");
                                   	                 return;
                                      }
                       // добавляем его в очередь
                                      q.emplace_front(move(framer));
                                      // разблокируем очередь
                                      qmutex.unlock();
                       printf("Kadr zapisan\n\n\n\n\n\n");
    
    
               	}
    
    
               	CLEAR(buf);
               		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
               		buf.memory = V4L2_MEMORY_MMAP;
    
               	        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
               	        xioctl(fd, VIDIOC_STREAMOFF, &type);//отключение потока видеозахвата
               	        printf("xioctl\n");
    
               	        for (i = 0; i < n_buffers; ++i){
               	            munmap(buffers[i].start, buffers[i].length);//Эта строка используется для освобождения памяти, которая была выделена для буферов.
               	            //Она вызывает функцию munmap для каждого буфера, которая освобождает ранее выделенную память.
    
               	    }
    
    
               	 printf("video saved\n");
    
                               close(fd);
                               delete[] buffers;
                               printf("close fd\n");
    
               cout << "[VIDEO_GRABBER] : stop" << endl;
           }
    
    
    
    void send_queue(int sock) {
        lock_guard<mutex> lk(qmutex);
        uint32_t t = q.size();
    cout<<"start queue"<<endl;
        // пишем кол-во кадров
        send(sock, (char*) &t, sizeof(t), 0);
        // высоту
        t = grows;
        send(sock, (char*) &t, sizeof(t), 0);
        // и ширину кадра
        t = gcols;
        send(sock, (char*) &t, sizeof(t), 0);
    
        cv::VideoWriter videoWriterig;
            videoWriterig.open("out23.avi", cv::VideoWriter::fourcc('M','J','P','G'), default_fps, cv::Size(gcols, grows));
            cout<<"1"<<endl;
        int rc = 0;
        while (!q.empty()) {
        	cout<<"cikl"<<endl;
            // берем самый старый кадр
            Mat & ref_mat = q.back();
            cout<<"ref_mat"<<endl;
            // сохраняем кадр в файл
            videoWriterig.write(ref_mat);
                    cout<<"writer"<<endl;
            // вычисляем кол-во байт в нем
            uint32_t total = (ref_mat.dataend - ref_mat.data);
            // шлем это значение, чтобы клиент знал сколько
            // ему нужно вычитать байт этого кадра
            rc = send(sock, (char*) &total, sizeof(total), 0);
            int sent = 0;
            while (total > 0) {
                // шлем непосредственно байты кадра
                rc = send(sock, ref_mat.data + sent, total, 0);
                if (rc == -1) break;
                sent  += rc;
                total -= rc;
            }
            // удаляем обработанный кадр из очереди
            q.pop_back();
        }
        // освобождаем ресурсы видеозаписи
        videoWriterig.release();
    }
    
    
    
    
    int main() {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror("socket");
            exit(1);
        }
        struct sockaddr_in addr;
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(default_port);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
            perror("ERR: binding failed!");
            exit(2);
        }
    
        listen(sock, 1);
    
        for (;;) {
            // запускаем граббинг кадров в очередь
            // параллельно нашему треду
            working = 1;
            std::thread t(&video_grabber_thread);
    
            // а сами в этом треде ждем подключение клиента
            struct sockaddr_in client;
            socklen_t len = sizeof(struct sockaddr_in);
            int new_socket = accept(sock, (struct sockaddr *)&client, &len);
    
            // к нам подключились, тогда останавливаем граббинг видео
            working = 0;
            t.join();
    
            if (new_socket == -1) { // если подключения клиента нет, то...
                cerr << "ERR: new_socket = " << new_socket << endl;
                //break;
            } else { //если подключился клиент, то ..
                send_queue(new_socket);
            }
        }
    
        close(sock); // закрытие сокета
        return 0;
    }

 ,

konstitycii ()

Есть ли смысл возиться с доступом к переменным?

Вот например есть ли отличие в исполняемом файле программы если написать public int var; private int var; protected int var? С точки зрения декомпиляции и реверс инжиниринга исполняемого файла? То есть если я напишу protected, переменная станет защищенной или нет от таких программ как art money?

 , ,

bad_master ()

stdio vs iostream и куча вопросов

Здравствуйте, коллеги! Везде пишут, что если пишешь на С++ то нужно использовать iostream.

Но я не могу понять в чем преимущество потокового ввода-вывода?

На мой взгляд, stdio.h удобнее в использовании как для вывода в терминал, так и для файловых операций. Кстати, этот подход более соответствует философии Linux, «все есть файл».

Где-то писали, что в С++ можно использовать stdio (без «.h»), но я таковой у себя в Fedora 37 не обнаруживаю.

У меня на данный момент задумка довольно элементарная: в зависимости от ситуации назначить файл/поток для ввода-вывода.

Например: Если процесс демонизируется, то для вывода назначить log файл. Если программа работает в обычном режиме, то писать в cout/stdout, cerr/stderr.

В обычном (ламповом) С все просто:

FILE * fout = fopen("logfile", "a+");

или:

FILE * fout = stdout

А как подобное сделать с потоками?

Да и нужны ли эти потоки?

В чем их преимущество?

 ,

HighMan ()

vbo, vao и шейдеры

Всем привет! Требуется отправить 6 вершин в GPU. А далее выводить сначала как два анимированных треугольника: (1,2,3)(3,4,1). Потом, тоже как два треугольника, но (4,1,2)(2,3,4). Как сделать так, чтобы не обновлять геометрию в основной программе, т.е. не очищать vao и создавать новый буфер (по сути из тех же самых вершин), и снова его отправлять в GPU. Может индексация тут поможет (можно ли обновлять только буфер индексов?) или в геометрическом шейдере что-то надо делать.

PS: opengl-4

 , , ,

Gyros ()

Итоги ежегодного глобального опроса пользователей C++

Опубликованы: https://isocpp.org/files/papers/CppDevSurvey-2023-summary.pdf

Ничего нового особенно: 10-20 лет опыта работы на C++, 20+ общего опыта программирования, MSVC, десктопная винда, линукс, инженерия (авионика и проч.), ембеддед, исходники зависимостей - часть билда, напрягает менеджмент зависимостей и время сборки, большинство используют C++11.

 

seiken ()

Обобщенные методы

Предположим у меня есть некоторый метод foo, который на вход принимает коллекцию каких-то значений. Причём это может быть и std::vector и std::array и std::array_view, например. Должен ли я писать перегруженную версию метода для каждого из этих типов или можно указать «Принимай тип однородной коллекции данных с произвольным доступом, не важно какой, лишь бы удовлетворяло этому условию»? В рамках стандарта до С++17 включительно.

Всем спасибо за ответы.

 , обобщенные типы,

LongLiveUbuntu ()

stack::push проверяет capacity, а pop ничего не проверяет

И где логика? Нарушение симметрии. Почему я должен платить за проверки в push, а pop для пустого стека приводит его в неконсистентное состояние?

 ,

Udacha ()

ПО средствами с,с++ как-то разместить на linux, чтобы использовать его только средствам интернет браузера на клиенте

где прочитать - ПО средствами с,с++ как-то разместить на linux, чтобы использовать его только средствам интернет браузера на клиенте.

 , , , ,

ustas1 ()

Стандартен ли long в Си?

Собственно вопрос. Описаны ли стандартом размеры всяких

long
long long
int
double
// И так далее

?
Если описаны, то чему равны их размеры? Или это компиляторозависимая платформоспецифичная особенность и лучше использовать к примеру uint64_t?

 , ,

Werenter ()

Опять хитрая очередь для 2х потоков на C++

Приветствую.

Сразу к сцути - пишет значит моя приблуда с 30 кадровой камеры мжпег кадры на SD карту на одноплатнике по кругу, для снижения нагрузки и получения некой равномерности делается это таким образом - меряю время в начале цикла записи, сравниваю после и оставшееся время либо сплю до частоты 10 фпс, либо пишу сразу следующий.

Все бы ничего, но иногда требуется как посмотреть текущее видео с камеры, которое перекодируется в х264 и отдается в ртсп, так и глянуть архив, которое хоть и не нагружает цпу у армки, но читает большие объемы с сд карты и шлет их активно в сеть по удп.

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

Но вот вопрос - как бы сделать так, чтобы на время записи-удаления из очереди И добавления в очередь - она НЕ БЛОКИРОВАЛАСЬ ??? Иба если блочить - очевидно опять будет неравномерность.

 ,

wolverin ()

Страуструп реагирует на критику безопасности C++

Отовсюду мы слышим стоны: C++ небезопасен! хватит использовать C++! АНБ призвало отказаться от C++, европейские законодатели готовят CRA, чтобы закрутить гайки для разработчиков небезопасного софта. Страуструп реагирует, вот его беседа о «Hardening C++»: https://youtu.be/eLLi0nWMUMs .

Начало:

  1. Когда я задумал C++ в 1979г., я взял C за основу. У меня не было знаний, чтобы создать ЯП с нуля;

  2. Я с самого начала всячески выступал за гораздо более строгую систему типов в C++;

  3. Меня раздражает, когда люди говорят о каком-то C/C++, это мифический ЯП, его не существует;

  4. Если мы говорим о безопасности, есть подмножество языка, которым можно ограничиться при написании безопасного софта. И тогда статические анализаторы типа clang-tidy или от MS позволят привести код довольно близко к виду «безопасный». Мы можем почти гарантировать, что в нем нет утечек памяти, болтающихся ссылок, и проч. Также можно опираться на безопасные библиотеки типа span, которые проверяют например границы доступа. И мы видем, что и другие ЯП прибегают к тем же мерам;

  5. другия ЯП, которые утверждают, что они безопасные и у них нет небезопасного кода… если в них есть способ вызвать C или C++, они уже не безопасные;

  6. Можно определить различные профили безопасности, которые определяют, какие фичи можно использовать, а какие - нет, чтобы избежать проблем, которые возникают из-за использования данных фич. Подобный подход используется в Ada. Но в принципе, это же делают статические анализаторы;

  7. Мы пишем библиотеку поддержки GSL, в которой есть такие вещи как span, которые позволяют избежать проблем с указателями;

  8. Если вы посмотрите на проблемный код, о котором все вопят, который приводит к проблемам, о которых вопят, это старый код, написанный в старом небезопасном стиле. Если посмотреть на то, как подобный код выглядит в новом стиле, этот новый код безопасен;

  9. Необходимо запретить разрабам компиляторов использовать UB как предлог для оптимизации;

и т.д. и т.п.

Выглядит довольно слабо. С самого начала был выбран небезопасный C в качестве основы системы типов. Как можно «выступать за безопасную систему типов» в ЯП, в котором в центре небезопасное ядро? Почему бы не набраться смелости и не сказать «да, C++ не безопасен, и никогда не будет безопасным; безопасность я выбросил, потому не нужна была, да и не потянул бы». Потом прошло много времени, проблемы набирались, как снежный ком, и теперь, когда C++ в каждой дырке, они начали чесаться: ой, нам нужны профили, нам нужно запретить небезопасные фичи; нам нужно то, это, третье, десятое, но вот статические анализаторы, они же примерно и делают необходимые проверки…

Особенно смешно выглядит сравнение с Адой и ее профилями. Потому что стандартная Ада, без всех ограничений, качественно безопаснее C++, и дело не в «безопасных библиотеках», а в более продуманной с самого начала системе типов. Но Страуструп не зря ссылается на Аду, скорее всего, понимает, что есть с самого начала грамотно спроектированные ЯП, а есть C++.

 , агония,

seiken ()