Проблема со строками - PullRequest
       42

Проблема со строками

3 голосов
/ 02 марта 2012

В настоящее время я отлаживаю значительную программу. Когда я прихожу к следующей строке кода:

value->binary_string = value_it->binary_string.substr(range->msb->value, range->size);

Программа не работает правильно. Здесь значение - указатель на структуру с членом с именем binary_string с типом std :: string. Когда я добираюсь до этой строки во время отладки, я вижу, что:

value_it->binary_string = "00000000000000000000000000000111"
range->msb->value = 0
range->size = 32

После выполнения этой строки кода значение-> двоичная_строка пуста! Я даже изменил строку на

value->binary_string = value_it->binary_string

и все равно не получается!

Когда я добираюсь до этой строки во время отладки, моя программа использует около 100 МБ памяти, поэтому я не думаю, что это проблема с памятью (хотя я запускаю Valgrind, как мы говорим, чтобы проверить это). Я использую Ubuntu 11.10, g ++ - 4.6 и libstdc ++ 6.

Кто-нибудь сталкивался с чем-то подобным раньше? Я понятия не имею, почему мои строки не работают!

Спасибо

Sam

EDIT1:

Тип значения NumberInst, определено ниже:

typedef std::string String;

struct NumberInst
{
    unsigned size;
    bool signed_;
    String binary_string;
    bool valid;
    unsigned value;

    NumberInst();
};

EDIT2:

Похоже, я немного сузил поиск. Во время отладки я попробовал несколько команд печати:

print value_it->binary_string
"00000000000000000000000000000111"
print value_it->binary_string[31]
'1'
print value_it->binary_string.substr(0, String::npos)
""
print value_it->binary_string.substr(0, 1)
""

Кажется, что substr не работает должным образом в этом контексте. Однако, когда я тестировал substr в своей основной функции, все работало нормально.

Ответы [ 2 ]

2 голосов
/ 02 марта 2012

Я обнаружил, что обычно есть две распространенные причины, когда происходят такие "странные" вещи:

  1. Вы допустили простую ошибку и просто пропускаете ее.
  2. Некоторыеповреждение памяти.

Чтобы проверить первую причину, внимательно прочитайте код, вызывающий нарушение, и примите сознательное решение о том, что делает код, а не то, что, по вашему мнению, должно быть.Очень легко пропустить очевидные ошибки, если предположить, что код должен делать то, чего на самом деле нет, особенно в коде, который вы просматривали некоторое время.Например, несколько месяцев назад я что-то отлаживал, и у меня возникла проблема с переменной, «волшебным образом» меняющей свое значение внезапно.Оказывается, я просто печатал неправильную переменную (да!), И я бы понял это раньше, если бы я читал то, что на самом деле говорит код.

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

1 голос
/ 02 марта 2012

Проблема была вызвана очень тонкой ошибкой.Где-то в моем проекте:

NumberInst* number = new NumberInst;
number->binary_string.reserve(size);
for (unsigned i = 0; i < size; i++)
    number->binary_string[i] = ...;

Исключение std :: out_of_range не будет выдано, потому что я предполагаю, что стандартная библиотека сравнивает индекс массива с емкостью строки (в отличие от размера строки).Вызов print в отладчике будет успешным, потому что он, вероятно, перебирает буфер, пока не достигнет символа '\ 0'.Однако

String str = number->binary_string

завершится сбоем, поскольку вполне вероятно, что стандартная библиотека скопирует буфер value_it-> binary_string из [0, size) и добавит символ '\ 0'.Поскольку размер value_it-> binary_string равен 0, копирование его содержимого завершится неудачно (как и substr и другие функции, зависящие от размера вызывающей строки).

Другими словами, проблема была вызвана вызовом

str.reserve(size);

вместо

str.resize(size);

Спасибо за вашу помощь всем!

Сэм

...