segfault при копировании массива в вектор в Linux - PullRequest
0 голосов
/ 16 декабря 2009

Я пытаюсь отладить устаревший код, написанный для Linux. Иногда приложение получает segfault, когда оно достигает вызова memcpy в следующем методе:

std::vector<uint8> _storage;
size_t _wpos;
void append(const uint8 *src, size_t cnt)
{
  if (!cnt)
  return;

  if (_storage.size() < _wpos + cnt)
    _storage.resize(_wpos + cnt);
  memcpy(&_storage[_wpos], src, cnt);
  _wpos += cnt;
}

Значения следующие:

_storage.size() is 1000
_wpos is 0
*src points to an array of uint8 with 3 values: { 3, 110, 20 }
cnt is 3

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

Кто-нибудь знает, как решить эту проблему?

Ответы [ 7 ]

4 голосов
/ 16 декабря 2009

Ваш код выглядит хорошо с точки зрения написанных данных.Вы абсолютно уверены, что передаете правильный src указатель?Что происходит, когда вы запускаете код с помощью отладчика, такого как GDB?Он должен остановиться на segfault, а затем вы можете распечатать значения _storage.size(), src и cnt.

Я уверен, что вы найдете (по крайней мере)это совсем не то, что вы ожидаете.Возможно, вы передали недействительный src;вы могли пройти нелепо большой cnt.

2 голосов
/ 16 декабря 2009

Я бы предложил запустить valgrind в вашей программе. Очень важно обнаружить раннее повреждение памяти, как это может быть в случае с вашей программой (поскольку это не систематический сбой, который вы получили).

1 голос
/ 16 декабря 2009

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

Кроме того, vector имеет встроенную поддержку управления памятью Expquisit. Вы можете вставить свои значения до конца:

vector.insert( src, src+cnt );

Это позволит расширить вектор до нужного размера и скопировать значения.

1 голос
/ 16 декабря 2009

Для значений, которые вы даете, я не понимаю, почему это могло бы привести к сбою.Возможно, что ваш segfault является отложенной ошибкой из-за более ранней ошибки управления памятью.Запись за конец вектора в какой-то более ранней функции может привести к повреждению некоторых внутренних членов вектора или к случайному освобождению части памяти, используемой вектором ранее.Я бы проверил другие функции, которые манипулируют вектором, чтобы узнать, выполняет ли какая-либо из них подозрительное приведение.

0 голосов
/ 16 декабря 2009

В комментарии к моему другому ответу вы сказали, что «вектор очищается в другом методе, поскольку он является переменной члена класса. Я протестирую вставку и посмотрю, что произойдет».

А как насчет безопасности потоков? Вы абсолютно уверены, что метод очистки не очищает «во время» изменения размера или сразу после него? Поскольку это «иногда» проблема, она может быть вызвана одновременным доступом к управлению памятью в vector.

0 голосов
/ 16 декабря 2009

Я вижу здесь одну проблему. Функция memcpy () копирует n байтов из памяти, поэтому, если cnt - это количество элементов, вам нужно * sizeof (uint8) при вызове memcpy.

0 голосов
/ 16 декабря 2009

Единственное, о чем я могу думать, это то, что _storage.resize () завершается ошибкой (что должно вызвать исключение bad_alloc).

Другой альтернативой будет добавление каждого значения отдельно с помощью вызова push_back () (хотя, возможно, намного медленнее).

...