Увеличение общей памяти: вектор символа *

Я пытаюсь сохранить char * в буст-контейнере, но это не удается. Мой символ * — это двоичные данные в 2048 блоках памяти. Эти двоичные данные представляют собой звук, записанный с помощью ALSA.
Но когда я сохраняю его в векторе строк общей памяти, он как-то видоизменяется, и я не могу понять, как это исправить.

Отредактируйте и, возможно, ответьте:
ALSA отправляет буферы void *, поэтому, если я могу создать вектор с общей памятью void *, я могу добиться цели. Поэтому мне нужно в основном создать вектор void *, и каждый void * должен иметь фиксированный размер (в данном случае: 2048). Я думаю, что boost::interprocess::basic_string это проблема
Конец Править

Вот полное объяснение:

Я пытаюсь слушать прямой ввод звука с помощью программы ALSA, а затем использовать другую программу, чтобы записать ее в файл (или обработать что-либо на нем)

Я начал с этого вопроса: Создайте вектор строк совместно используемой памяти

Теперь я застрял, я не очень хорошо знаю импульс.
Я создал GitHub (https://github.com/Waxo/nodetest) с полным проектом. Элемент управления Alsa с методом listen с обратным вызовом просто вызывает метод с (char *, int) прототипом.

После создания проекта вы можете запустить ./nodetest а также ./nodetest arg когда ./nodetest сказал «иди»

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <iostream>
#include <atomic>
#include <future>

#include <iostream>
#include <alsa_control.h>

using std::cout;
using std::endl;

typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> MyShmString;
typedef boost::interprocess::allocator<MyShmString, boost::interprocess::managed_shared_memory::segment_manager> StringAllocator;
typedef boost::interprocess::vector<MyShmString, StringAllocator> MyShmStringVector;class lambda_class {
public:
void lambda_callback(char *c, int rc) {
this->sample_count_ += rc;
this->output_file_.write(c, rc * 2);
}

lambda_class(std::string filename) {
this->filename_ = filename;
this->sample_count_ = 0;
this->output_file_.open(this->filename_, std::ios::binary);
write_header_wav(this->output_file_, 16000, 16, MONO, 10000);
}

~lambda_class() {
this->output_file_.close();
this->output_file_.open(this->filename_,
std::ios::binary | std::ios::in);
write_header_wav(this->output_file_, 16000, 16, MONO, this->sample_count_);
}

private:
std::string filename_;
int sample_count_;
std::ofstream output_file_;
lambda_class(const lambda_class &a) = delete;
};

class input_class {
public:
input_class() {
boost::interprocess::shared_memory_object::remove("MySharedMemory");
this->shm = new boost::interprocess::managed_shared_memory(boost::interprocess::create_only, "MySharedMemory",
1000000);
CharAllocator charallocator(this->shm->get_segment_manager());
StringAllocator stringallocator(this->shm->get_segment_manager());
this->myshmvector = shm->construct<MyShmStringVector>("myshmvector")(stringallocator);
};

~input_class() {
lambda_class *lc = new lambda_class("listener_vector.wav");
char *c = (char *) malloc(2048);
for (MyShmStringVector::iterator it = this->myshmvector->begin(); it != this->myshmvector->end(); it++) {
strcpy(c, it->c_str());
lc->lambda_callback(c, 2048);
}
delete lc;
boost::interprocess::shared_memory_object::remove("MySharedMemory");
this->shm->destroy_ptr(this->myshmvector);
}

void to_node(char *c, int rc) {
CharAllocator charallocator(this->shm->get_segment_manager());
StringAllocator stringallocator(this->shm->get_segment_manager());
MyShmString mystring(charallocator);
mystring = c;
this->myshmvector->insert(this->myshmvector->begin(), mystring);
}

private:
boost::interprocess::managed_shared_memory *shm;
MyShmStringVector *myshmvector;
};

void listener() {
lambda_class *ctc = new lambda_class("writer.wav");
char *c = (char *) malloc(2048);
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only, "MySharedMemory");
MyShmStringVector *myvector = segment.find<MyShmStringVector>("myshmvector").first;for (MyShmStringVector::iterator it = myvector->begin(); it != myvector->end(); it++) {
strcpy(c, std::string(it->begin(), it->end()).c_str());
ctc->lambda_callback(c, 2048);
}

delete ctc;
return;
}

int main(int argc, char **argv) {
alsa_control *ac = new alsa_control(16000, 2048, 16, MONO);

if (argc == 1) {

input_class *ic = new input_class();
ac->listen_with_callback(std::bind(&input_class::to_node, ic, std::placeholders::_1, std::placeholders::_2),
"listener");
sleep(5);
ac->stop();
cout << "Go" << endl;
sleep(10);

delete ic;
delete ac;
} else {
auto th = std::async(std::launch::async, listener);
th.get();
}return 0;
}

Я просто пытаюсь использовать мои звуки в нескольких процессах со структурой, в которой я могу использовать ее и делиться ею (я буду создавать и организовывать все мои программы).
Символ * может иметь фиксированный размер, если я могу его использовать, все хорошо.

Редактировать :
Моя проблема в том, что записанные звуки:

  • listener_vector.wav из того же процесса
  • writer.wav из другой программы

Неверно, я думаю, что MyShmString мутировать их в недопустимые двоичные данные.

0

Решение

В дополнение к тому, что все остальные говорили,

  • у вас была ошибка в примерах -> преобразование количества байтов. Это приводит к тому, что половина выходных данных является неинициализированными данными.

    void lambda_callback(char *c, int rc) {
    this->sample_count_ += rc;
    this->output_file_.write(c, rc * 2);
    }
    

    становится

    void lambda_callback(char *c, int rc) {
    this->sample_count_ += rc/2;
    this->output_file_.write(c, rc);
    }
    

    НОТА смотрите также rc*2 в to_node ниже

  • Вы вставили строки в вектор впереди — это приводит к тому, что фрагменты аудио выводятся в обратном порядке. Кроме того, назначение mystring пренебрег rc Информация

    void to_node(char *c, int rc) {
    CharAllocator charallocator(this->shm->get_segment_manager());
    StringAllocator stringallocator(this->shm->get_segment_manager());
    MyShmString mystring(charallocator);
    mystring = c; // OOPS! this cuts off at any NUL char
    this->myshmvector->insert(this->myshmvector->begin(), mystring);
    }
    

    становится

    void to_node(char *c, int rc) {
    _myshmvector->emplace_back(c, rc*2, shm->get_segment_manager());
    }
    
  • вместо того, чтобы полагаться на фиксированный размер буфера, вы должны использовать размер строки при итерации общего вектора. Кроме того не использовать strcpy для двоичных данных:

    void listener() {
    lambda_class ctc("writer.wav");
    
    char *c = (char *) malloc(2048);
    
    boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only, "MySharedMemory");
    MyShmStringVector *myvector = segment.find<MyShmStringVector>("myshmvector").first;for (MyShmStringVector::iterator it = myvector->begin(); it != myvector->end(); it++) {
    //strcpy(c, std::string(it->begin(), it->end()).c_str()); //HUHUH!?!
    strcpy(c, it->c_str());
    ctc.lambda_callback(c, 2048);
    }
    }
    

    будет выглядеть так:

    void listener() {
    lambda_class ctc("writer.wav");
    
    char c[4096];
    
    boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only, "MySharedMemory");
    MyShmStringVector *myvector = segment.find<MyShmStringVector>("myshmvector").first;
    
    for (MyShmStringVector::iterator it = myvector->begin(); it != myvector->end(); it++) {
    //strcpy(c, std::string(it->begin(), it->end()).c_str()); //HUHUH!?!
    assert(it->size()<=sizeof(c));
    memcpy(c, it->c_str(), it->size());
    ctc.lambda_callback(c, it->size());
    }
    }
    
  • не malloc в с ++. У вас были те, которые просочились

  • ваш тестовый сценарий является грубым (но я полагаю, вы знали об этом, и это было для простоты?)

  • Вместо «волшебного» файла заново открывают, просто seekp:

    this->output_file_.close();
    this->output_file_.open(this->filename_, std::ios::binary | std::ios::in);
    

    становится

    output_file_.seekp(0ul);
    

Потяните Запрос на GitHub

commit 660208ff3fe792112ccae70a61e8a2442a853664
Author: Seth Heeren <sgheeren@gmail.com>
Date:   Mon Aug 17 00:13:31 2015 +0200

Fixes, now

./nodetest & sleep 6; ./nodetest 1; fg; md5sum *.wav

results in proper identical files, e.g.

$ ./nodetest & sleep 6; ./nodetest 1; fg; md5sum *.wav
[1] 12350
Go
./nodetest
ff083a6344d7037da9c4f6d730239f30  listener_vector.wav
ff083a6344d7037da9c4f6d730239f30  listener.wav
ff083a6344d7037da9c4f6d730239f30  writer.wav

commit 04a5dec3da322dab196bfe568f52db6d9ed68b43
Author: Seth Heeren <sgheeren@gmail.com>
Date:   Sun Aug 16 23:30:40 2015 +0200

we have repro

main.cc

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <iostream>
#include <atomic>
#include <future>

#include <iostream>
#include <alsa_control.h>

using std::cout;
using std::endl;

typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> MyShmString;
typedef boost::interprocess::allocator<MyShmString, boost::interprocess::managed_shared_memory::segment_manager> StringAllocator;
typedef boost::interprocess::vector<MyShmString, StringAllocator> MyShmStringVector;class lambda_class {
public:
void lambda_callback(char *c, int rc) {
this->sample_count_ += rc/2;
this->output_file_.write(c, rc);
}

lambda_class(std::string filename) {
this->filename_ = filename;
this->sample_count_ = 0;
this->output_file_.open(this->filename_, std::ios::binary);
write_header_wav(this->output_file_, 16000, 16, MONO, 10000);
}

~lambda_class() {
/*
*this->output_file_.close();
*this->output_file_.open(this->filename_, std::ios::binary | std::ios::in);
*/
output_file_.seekp(0ul);
write_header_wav(this->output_file_, 16000, 16, MONO, this->sample_count_);
}

private:
std::string filename_;
int sample_count_;
std::ofstream output_file_;
lambda_class(const lambda_class &a) = delete;
};

class input_class {
public:
input_class() {
boost::interprocess::shared_memory_object::remove("MySharedMemory");
this->shm = new boost::interprocess::managed_shared_memory(boost::interprocess::create_only, "MySharedMemory",
1000000);
CharAllocator charallocator(this->shm->get_segment_manager());
StringAllocator stringallocator(this->shm->get_segment_manager());
this->myshmvector = shm->construct<MyShmStringVector>("myshmvector")(stringallocator);
};

~input_class() {
lambda_class lc("listener_vector.wav");
char c[4096];
for (MyShmStringVector::iterator it = this->myshmvector->begin(); it != this->myshmvector->end(); it++) {
assert(it->size()<=sizeof(c));
memcpy(c, it->c_str(), it->size());
lc.lambda_callback(c, it->size());
}
boost::interprocess::shared_memory_object::remove("MySharedMemory");
shm->destroy_ptr(this->myshmvector);
}

void to_node(char *c, int rc) {
this->myshmvector->emplace_back(c, rc*2, shm->get_segment_manager());
}

private:
boost::interprocess::managed_shared_memory *shm;
MyShmStringVector *myshmvector;
};

void listener() {
lambda_class ctc("writer.wav");

char c[4096];

boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only, "MySharedMemory");
MyShmStringVector *myvector = segment.find<MyShmStringVector>("myshmvector").first;

for (MyShmStringVector::iterator it = myvector->begin(); it != myvector->end(); it++) {
//strcpy(c, std::string(it->begin(), it->end()).c_str()); //HUHUH!?!
assert(it->size()<=sizeof(c));
memcpy(c, it->c_str(), it->size());
ctc.lambda_callback(c, it->size());
}
}

int main(int argc, char **argv) {
alsa_control ac(16000, 2048, 16, MONO);

if (argc == 1) {
input_class ic;
ac.listen_with_callback(std::bind(&input_class::to_node, &ic, std::placeholders::_1, std::placeholders::_2), "listener");
sleep(5);
ac.stop();
cout << "Go" << endl;
sleep(10);
} else {
//    std::atomic<bool> done(false);
auto th = std::async(std::launch::async, listener);
//    done.store(true, std::memory_order_relaxed);
th.get();
}
return 0;
}
1

Другие решения

Я не исследовал вашу стену кода, но в вашем вопросе я заметил, что вы говорите:

Я пытаюсь сохранить символ * внутри буст-контейнера

а потом

Мой символ * двоичные данные

а потом

Я думаю, что boost :: interprocess :: basic_string si проблема

Теперь, это помогло бы, если бы вы указали точный тип вместо того, чтобы просто сказать «контейнер повышения» — какой контейнер, но если вы пытаетесь хранить двоичные данные в строковом классе — НООООООО, это не то, как вы используете строку. Вы храните текст в виде строк, а не двоичных данных. Для использования двоичных данных std::vector<char>,

В частности, если вы используете что-то похожее на это где-нибудь в вашем коде

string s = (char*) binary_data;

Строка будет обрезан при первом обнаруженном нуле!

1

Я изменил ваш пример кода для использования межпроцессного vector из int8_t который можно рассматривать как один из способов правильного хранения двоичных данных.

Конечно, выходной файл был неправильным из-за этой строки:
this->output_file_.write(c, rc * 2);
Если вы хотите записать вдвое больше данных, вам нужно позвонить write дважды:

this->output_file_.write(c, rc);
this->output_file_.write(c, rc);

Переходя rc * 2 заставляет записывать мусорные данные после первых 2048 байтов.

Другая потенциальная проблема — эта строка:
this->myshmvector->insert(this->myshmvector->begin(), mystring);
Здесь вы храните ваши данные в обратном порядке. Это было твоё намерение? В моем фиксированном примере я изменил его, чтобы хранить данные в порядке их поступления.

Третьей потенциальной проблемой могут быть нули в двоичных данных, как упомянуто @sashoalm.

Вот фиксированная часть кода, в который я внес изменения:

typedef boost::interprocess::allocator<int8_t, boost::interprocess::managed_shared_memory::segment_manager>  ShmemAllocator;
typedef boost::interprocess::vector<int8_t, ShmemAllocator> MyVector;class lambda_class {
public:
void lambda_callback(int8_t *c, int rc) {
this->sample_count_ += rc;
//this->output_file_.write(c, rc * 2); // this is not going to work, to write twice as much data you need to call write() twice
this->output_file_.write(reinterpret_cast<char*>(c), rc);
//this->output_file_.write(reinterpret_cast<char*>(c), rc); // uncomment this line to write twice as much data
}

lambda_class(std::string filename) {
this->filename_ = filename;
this->sample_count_ = 0;
this->output_file_.open(this->filename_, std::ios::binary);
write_header_wav(this->output_file_, 16000, 16, MONO, 10000);
}

~lambda_class() {
this->output_file_.close();
this->output_file_.open(this->filename_,
std::ios::binary | std::ios::in);
write_header_wav(this->output_file_, 16000, 16, MONO, this->sample_count_);
}

private:
std::string filename_;
int sample_count_;
std::ofstream output_file_;
lambda_class(const lambda_class &a) = delete;
};

class input_class {
public:
input_class() {
boost::interprocess::shared_memory_object::remove("MySharedMemory");
this->shm = new boost::interprocess::managed_shared_memory(boost::interprocess::create_only, "MySharedMemory",
1000000);
const ShmemAllocator alloc_inst(this->shm->get_segment_manager());
this->myshmvector = shm->construct<MyVector>("myshmvector")(alloc_inst);
};

~input_class() {
lambda_class *lc = new lambda_class("listener_vector.wav");
int8_t *c = (int8_t *)malloc(2048);
for (MyVector::iterator it = this->myshmvector->begin(); it != this->myshmvector->end(); it+=2048) {
memcpy(c, &*it, 2048);
lc->lambda_callback(c, 2048);
}
delete lc;
boost::interprocess::shared_memory_object::remove("MySharedMemory");
this->shm->destroy_ptr(this->myshmvector);
}

void to_node(int8_t *c, int rc) {
//this->myshmvector->insert(this->myshmvector->begin(), c, c+2048); // if your intention was to reverse the data then uncomment this line and comment out the line below
this->myshmvector->insert(this->myshmvector->end(), c, c + 2048); // storing data in order as it comes
}

private:
boost::interprocess::managed_shared_memory *shm;
MyVector *myshmvector;
};

void listener() {
lambda_class *ctc = new lambda_class("writer.wav");
int8_t *c = (int8_t *)malloc(2048);
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only, "MySharedMemory");
MyVector *myvector = segment.find<MyVector>("myshmvector").first;for (MyVector::iterator it = myvector->begin(); it != myvector->end(); it+=2048) {
memcpy(c, &*it, 2048);
ctc->lambda_callback(c, 2048);
}

delete ctc;
return;
}
1

Вопрос не ясен, поэтому я бы посоветовал улучшить вопрос.

Тем не менее, я вижу ошибку в вашем коде:
Вы выделяете массив с 2048 элементами

char *c = (char *) malloc(2048);

а затем вы пишете вдвое больше в lambda_callback ()

 void lambda_callback(char *c, int rc) {
this->sample_count_ += rc;
this->output_file_.write(c, rc * 2);
}

тебе нужно пройти гс вместо RC * 2 написать();

-1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector