В файле JNI .cpp у меня есть структура с SoundTouch * (SoundTouch — это обработка звука C ++, которую я обертываю для использования в проекте Android), и я инициализирую вектор структур как глобальные объекты, подобные этому:
struct SoundTouchExt
{
SoundTouch* sTouch;
queue<signed char>* fBufferOut;
int channels;
int sampleRate;
float tempoChange;
int pitchSemi;
int bytesPerSample;
SoundTouchExt()
{
sTouch = new SoundTouch();
fBufferOut = new queue<signed char>();
}
};
const int MAX_TRACKS = 16;
vector<SoundTouchExt> sProcessors(MAX_TRACKS);
Это работает, по крайней мере, если я использую только один из объектов SoundTouchExt за раз в моей программе (это своего рода другая история, но, возможно, связанная — с несколькими экземплярами в игре вызывает искаженный вывод).
Однако, если я объявлю это так SoundTouch sTouch;
закомментируйте new
и измените его использование соответствующим образом ( ->
в .
), указатели на ссылки, я компилирую нормально, но я получаю ОШИБКУ 11 (ошибка сегмента), как только программа пытается использовать объект.
Вот где это происходит:
...
SoundTouchExt& soundTouch = sProcessors.at(track);
setup(soundTouch, channels, samplingRate, bytesPerSample, tempo, pitchSemi);
}
static void setup(SoundTouchExt& soundTouch, int channels, int sampleRate, int bytesPerSample, float tempoChange, float pitchSemi)
{
SoundTouch& sTouch = soundTouch.sTouch;
soundTouch.channels = channels;
soundTouch.sampleRate = sampleRate;
soundTouch.bytesPerSample = bytesPerSample;
soundTouch.tempoChange = tempoChange;
soundTouch.pitchSemi = pitchSemi;
sTouch.setSampleRate(sampleRate);
sTouch.setChannels(channels);
...
}
После небольшого исследования я думаю, что это может быть статический порядок инициализации фиаско. Я не вижу глобальных переменных в исходном коде библиотеки, но я не знаю достаточно о C ++, чтобы знать, что еще искать.
Что моё наблюдение может подсказать по поводу библиотеки (или, может быть, я что-то не так делаю)?
Я верю твоему SoundTouch
Структура / класс имеет проблему в своем конструкторе копирования и / или операторе присваивания. Или вы даже не написали их, но нужно.
Почему я говорю это, когда я даже не вижу код для SoundTouch? Что ж…
Ваш SoundTouchExt
есть проблемы с тем, как он управляет своим членом sTouch (и fBufferOut также). Каждый экземпляр создает свой собственный sTouch, но у вас нет конструктора копирования или оператора присваивания, чтобы иметь дело с членами sTouch, когда ваши объекты копируются. Значения по умолчанию, предоставленные компилятором, просто сделают поверхностную копию для каждого члена. Таким образом, если один объект SoundTouchExt когда-либо будет назначен другому, то оба они получат указатели sTouch, указывающие на один и тот же SoundTouch. Я сомневаюсь, что ты когда-нибудь хотел, чтобы это произошло. Однако, поскольку у вас также нет деструктора для очистки этих выделений, вы можете на время обойтись без этой ситуации (поскольку утечка памяти будет легко пропустить).
И похоже, что вам действительно случается, чтобы сойти с рук во время использования vector<SoundTouchExt>
, Вектор управляет внутренним массивом. Когда вы добавляете записи в вектор, ему иногда может не хватать места в его текущем массиве и, следовательно, необходимо создать новый массив для хранения дополнительной записи. При этом он должен скопировать все записи из старого массива в новый. Так что используется конструктор копирования и / или оператор присваивания SoundTouchExt. Вы не замечаете этого, потому что ситуация двух экземпляров SoundTouchExt, использующих один и тот же SoundTouch, существует только на короткое время, прежде чем один из старого массива будет уничтожен. А поскольку в SoundTouchExt отсутствует деструктор, проблема не возникает.
Теперь рассмотрим, как все меняется, когда элемент sTouch является фактическим экземпляром SoundTouch, а не указателем. В этом случае, когда объект SoundTouchExt копируется и, таким образом, копируется элемент sTouch, это означает, что компилятор будет использовать конструктор копирования / оператор присваивания SoundTouch. И мы знаем, что ваш вектор может вызвать это.
Поскольку у вашего SoundTouchExt есть проблемы, которые я описал при копировании, я подозреваю, что у вашего SoundTouch также есть проблемы. Если это так, то к тому времени, когда вы попытаетесь использовать элемент sTouch, он, вероятно, уже был скопирован и, таким образом, вызвал какую-то проблему. Эта проблема приводит к вашей аварии.
Итак, чтобы исправить положение, у вас есть несколько вариантов:
new
без необходимости писать какой-либо дополнительный код.Других решений пока нет …