В gdb вы можете многое сделать, чтобы изменить поведение вашей программы, когда она достигает точки останова без остановок. Команда печати также может быть использована для изменения значений, например, print i=0
фактически устанавливает i в ноль.
Просто помните, что все эти изменения и взломы должны быть перенесены обратно в исходный код и протестированы снова! За прошедшие годы я потерял много отличных правок, выполняя встроенные хаки в коде, а затем завершал работу, не просматривая изменения.
Вы ступаете в обувь Raymond Chen. Он сделал ту же самую вещь, пишущий китайский словарь в неуправляемом C++. Rico Mariani сделал также, пишущий это в C#. Г-н Mariani сделал одну версию. Г-н Chen записал 6 версий, пытаясь соответствовать перфекту версии Mariani. Он в значительной степени переписал значительные блоки библиотеки времени выполнения C/C++ для получения там.
Управляемый код получил намного больше уважения после этого. Средство выделения GC невозможно разбить. Проверьте это сообщение в блоге на ссылки. Это сообщение в блоге могло бы заинтересовать Вас также, поучительный, чтобы видеть, как семантика значения STL является частью проблемы.
Это очень кажется, что Raymond Chen по сравнению с C++ Rico Mariani по сравнению с китайским/Английским исполнением словаря C# печет прочь. Raymond потребовались несколько повторений для избиения C#.
Возможно, существуют идеи там, которые помогли бы.
Черт. избавьтесь от CStrings...
судите профилировщика также. действительно ли Вы уверены, что только выполняли код отладки?
станд. использования:: строка вместо этого.
Править:
Я просто сделал простой тест ctor и dtor сравнений.
CStringW, кажется, берет между 2 и 3 раза временем, чтобы сделать новое/удал.
выполненный с помощью итераций, 1000000 раз делая новый/удаляющий для каждого типа. Ничто иное - и GetTickCount () вызов прежде и после каждого цикла. Последовательно добирайтесь дважды, как жаждут CStringW.
Это не решает Вашу всю проблему, хотя я подозреваю.
Править: Я также не думаю, что использование строки или CStringW является реальным проблема - существует что-то еще продолжающееся, который вызывает Вашу проблему.
(но ради бога, используйте stl так или иначе!)
Необходимо представить его. Это - авария.
Если это - словарь только для чтения затем, следующее должно работать на Вас.
Use fseek/ftell functionality, to find the size of the text file.
Allocate a chunk of memory of that size + 1 to hold it.
fread the entire text file, into your memory chunk.
Iterate though the chunk.
push_back into a vector<const char *> the starting address of each line.
search for the line terminator using strchr.
when you find it, deposit a NUL, which turns it into a string.
the next character is the start of the next line
until you do not find a line terminator.
Insert a final NUL character.
Можно теперь использовать вектор, для получения указателя, который позволит Вам получить доступ к соответствующему значению.
Когда Вы закончите со своим словарем, освободите память, позвольте вектору умереть при выходе из объема.
[РЕДАКТИРОВАНИЕ] Это может быть немного более сложно на платформе DOS как разделитель строки, является CRLF.
В этом случае используйте strstr, чтобы найти, что он, и инкремент 2 находит запуск следующей строки.
В каком контейнере Вы храните свои строки? Если это - a std::vector
из CStringW
и если Вы не имеете reserve
- редактор достаточно памяти заранее, Вы обязаны получить удар. A vector
обычно изменяет размер, после того как это достигает, это - предел (который не очень высок), и затем копирует полноту к новой ячейке памяти, которая является, может дать Вам большой хит. Как Ваш vector
растет экспоненциально (т.е. если начальный размер равняется 1, в следующий раз, когда он выделяет 2, в 4 следующих раза вперед, хит становится все меньше и меньше частым).
Это также помогает знать, какой длины отдельные строки. (Время от времени :)
Загрузите строку в единственный буфер, проанализируйте текст для замены разрывов строки строковыми разделителями ('\0'), и указатели использования в тот буфер для добавления к набору.
Кроме того - например, если необходимо сделать, преобразование ANSI/UNICODE во время загрузки - использует средство выделения блока, которое жертвует отдельными элементами удаления.
class ChunkAlloc
{
std::vector<BYTE> m_data;
size_t m_fill;
public:
ChunkAlloc(size_t chunkSize) : m_data(size), m_fill(0) {}
void * Alloc(size_t size)
{
if (m_data.size() - m_fill < size)
{
// normally, you'd reserve a new chunk here
return 0;
}
void * result = &(m_data[m_fill]);
m_fill += size;
return m_fill;
}
}
// all allocations from chuunk are freed when chung is destroyed.
Не взломал бы это вместе через десять минут, но 30 минут, и некоторое тестирование звучит прекрасным :)
Спасибо все Вы для Ваших проницательных комментариев. Upvotes для Вас!:-)
Я должен признать, что не был подготовлен к этому вообще - что C# разобьет живущее дерьмо из старого доброго C++ таким образом. Не читайте, что как преступление к C++, но вместо этого что удивительно хороший диспетчер памяти, который находится в Платформе.NET.
Я решил предпринять шаги назад и вести этот бой на арене InterOp вместо этого! Таким образом, я сохраню свой код C# и позволю моему старому C++ кодировать, говорят с кодом C# по COM-интерфейсу.
Много вопросов спросили о моем коде, и я попытаюсь ответить на некоторых из них:
Компилятором была Visual Studio 2008 и не, я не выполнял отладочную сборку.
Файл был считан со средством чтения файлов UTF8, которое я загрузил от сотрудника Microsoft, который опубликовал его на их сайте. Это возвратило CStringW, и приблизительно 30% времени были на самом деле потрачены, там просто читая файл.
Контейнер, в котором я сохранил строки, был просто вектором фиксированного размера указателей на CStringW, и он никогда не изменялся.
Править: Я убежден, что предложения, которые мне дали, будут действительно работать, и что я, вероятно, мог победить код C#, если бы я инвестировал достаточно времени в него. С другой стороны, выполнение так не обеспечило бы клиентского значения вообще, и единственная причина выжить с ним будет состоять в том, чтобы только доказать, что оно могло быть сделано...
При работе со строковыми классами необходимо всегда взглянуть на ненужные операции, например, не используйте конструкторов, конкатенацию и такие операции слишком часто, особенно избегайте их в циклах. Я предполагаю, что существует некоторая причина кодировки символов, что Вы используете CStringW, таким образом, Вы, вероятно, не можете использовать что-то другое, это было бы другим способом оптимизировать Ваш код.
Проблема не в CString, а в том, что вы выделяете много маленьких объектов - распределитель памяти по умолчанию не оптимизирован для этого.
Напишите свой собственный распределитель - выделите большой кусок памяти, а затем просто переместите указатель в него при распределении. Это то, что на самом деле делает распределитель .NET. Когда будете готовы, удалите весь буфер.
Я думаю, что был образец написания пользовательских операторов new / delete в (More) Effective C ++