Повреждение "кучи" под Win32; как расположиться?

Если вы не против установки пакета для него, вы можете использовать json-tricks :

pip install json-tricks

После этого вам просто нужно импортировать dump(s) из json_tricks вместо json, и он обычно работает:

from json_tricks import dumps
json_str = dumps(cls_instance, indent=4)

, который даст

{
        "__instance_type__": [
                "module_name.test_class",
                "MyTestCls"
        ],
        "attributes": {
                "attr": "val",
                "dct_attr": {
                        "hello": 42
                }
        }
}

И это в основном это!


Это будет отлично работать в целом. Существуют некоторые исключения, например. если в __new__ происходят особые вещи, или происходит больше метаклассической магии.

Очевидно, что загрузка также работает (в противном случае в чем смысл):

from json_tricks import loads
json_str = loads(json_str)

Это предполагает, что module_name.test_class.MyTestCls могут быть импортированы и не изменены несовместимыми способами. Вы вернете экземпляр, а не какой-либо словарь или что-то еще, и он должен быть идентичной копией того, который вы сбросили.

Если вы хотите настроить, как что-то получает (де) сериализован, вы можете добавить специальные методы для вашего класса, например:

class CustomEncodeCls:
        def __init__(self):
                self.relevant = 42
                self.irrelevant = 37

        def __json_encode__(self):
                # should return primitive, serializable types like dict, list, int, string, float...
                return {'relevant': self.relevant}

        def __json_decode__(self, **attrs):
                # should initialize all properties; note that __init__ is not called implicitly
                self.relevant = attrs['relevant']
                self.irrelevant = 12

, который в качестве примера сериализует только часть параметров атрибутов.

И как бесплатный бонус, вы получаете (de) сериализация массивов numpy, date & amp; временами, упорядоченные карты, а также возможность включать комментарии в json.

Отказ: я создал json_tricks , потому что у меня была та же проблема, что и вы.

59
задан 11 revs, 4 users 55% 16 September 2012 в 10:09
поделиться

15 ответов

Моим предпочтительным вариантом был бы выделенный инструмент "кучи" такой как pageheap.exe .

новая Перезапись и удаляет, могло бы быть полезным, но это не ловит выделения, фиксировавшие кодом низшего уровня. Если это - то, что Вы хотите, лучше для Хождения в обход low-level alloc API с с помощью Microsoft Detours.

Также проверки работоспособности, такие как: проверьте свое соответствие библиотек времени выполнения (выпуск по сравнению с отладкой, многопоточной по сравнению с однопоточным, dll по сравнению со статическим lib), ищите, плохо удаляет (например, удалите, где удаляют [], должен был использоваться), удостоверьтесь, что Вы не смешиваете и соответствуете своим выделениям.

Также попытка, выборочно выключающая потоки и, видит, когда/если проблема уходит.

, На что стек вызовов и т.д. похож во время первого исключения?

28
ответ дан Michael Kelley 24 November 2019 в 18:32
поделиться

Мало времени я должен был решить подобную проблему. Если проблема все еще существует, я предлагаю, чтобы Вы сделали это: Контролируйте все вызовы к новому/удаляет и malloc/calloc/realloc/free. Я делаю единственный DLL, экспортирующий функцию для регистра все вызовы. Эта функция получает параметр для идентификации Вашего источника кода, указателя на выделенную область и тип вызова, сохраняющего эту информацию в таблице. Все выделили/освободили пару, устраняется. В конце или после необходимости в Вас звонят другой функции для, создают отчет для левых данных. С этим можно определить неправильные вызовы (новый/свободный или malloc/delete) или пропавшие без вести. Если имеют какой-либо случай буфера, перезаписанного в Вашем коде, сохраненная информация может быть неправильной, но каждый тест может обнаруживать/обнаруживать/включать решение определенного отказа. Много выполнений, чтобы помочь определить ошибки. Удача.

0
ответ дан lsalamon 24 November 2019 в 18:32
поделиться

Предложение Graeme пользовательского malloc/free является хорошей идеей. Посмотрите, можно ли характеризовать некоторый шаблон о повреждении, чтобы дать Вам дескриптор для усиления.

, Например, если это всегда находится в блоке того же размера (говорят 64 байта) тогда изменяют Вашу malloc/free пару, чтобы всегда выделить 64-байтовые блоки на их собственной странице. Когда Вы освобождаете 64-байтовый блок, тогда устанавливает биты защиты памяти на той странице для предотвращения чтений и вины (использующий VirtualQuery). Тогда любой пытающийся получить доступ к этой памяти генерирует исключение вместо того, чтобы повредить "кучу".

Это действительно предполагает, что количество выдающихся 64-байтовых блоков только умеренно, или у Вас есть большая память для записи в поле!

0
ответ дан Rob Walker 24 November 2019 в 18:32
поделиться

Если Вы принимаете решение переписать новый/удаляющий, я сделал это и имею простой исходный код в:

http://gandolf.homelinux.org/~smhanov/blog/?id=10

Это ловит утечки памяти и также вставляет защитные данные прежде и после блока памяти для получения повреждения "кучи". Можно просто интегрироваться с ним путем помещения #include "debug.h" наверху каждого файла CPP и определения ОТЛАДКИ и DEBUG_MEM.

1
ответ дан Steve Hanov 24 November 2019 в 18:32
поделиться

Мое первое действие было бы следующие:

  1. Сборка двоичные файлы в версии "Выпуска", но создающий файл информации об отладке (Вы найдете эту возможность в настройках проекта).
  2. Использование доктор Watson как defualt отладчик (DrWtsn32-I) на машине, на которой Вы хотите воспроизвести проблему.
  3. Repdroduce проблема. Доктор Watson произведет дамп, который мог бы быть полезным в дальнейшем анализе.

Другая попытка могла бы использовать WinDebug в качестве средства отладки, которое довольно мощно быть одновременно также легким.

, Возможно, эти инструменты позволят Вам, по крайней мере, сужать проблему к определенному компоненту.

И действительно ли Вы уверены, что все компоненты проекта имеют корректные настройки библиотеки времени выполнения (вкладка C/C++, категория Генерации кода в настройках проекта VS 6.0)?

1
ответ дан Piotr Tyburski 24 November 2019 в 18:32
поделиться

Таким образом от ограниченной информации Вы имеете, это может быть комбинацией одной или нескольких вещей:

  • Плохое использование "кучи", т.е. дважды освобождает, читайте после свободный, запишите после свободный, установив флаг HEAP_NO_SERIALIZE с выделениями, и освобождает от нескольких потоков на той же "куче"
  • Из памяти
  • Плохой код (т.е. переполнение буфера, недостаточные наполнения буфера, и т.д.)
  • проблемы "Синхронизации"

, Если это во всех первых двух, но не последнем, необходимо было поймать его к настоящему времени с любым pageheap.exe.

, Который наиболее вероятный означает, это происходит из-за того, как код получает доступ к общей памяти. К сожалению, разыскивание, которое будет довольно болезненным. Несинхронизируемый доступ к общей памяти часто проявляет, поскольку странная "синхронизация" выходит. Вещи как не использование получают/выпускают семантику для синхронизации доступа к общей памяти с флагом, не использование блокировок соответственно, и т.д.

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

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

, Когда Вы тестировали с VS2008, Вы работали с HeapVerifier с набором Памяти Варенья к Да? Это могло бы уменьшить влияние производительности средства выделения "кучи". (Плюс, необходимо работать с ним, Отладка-> Запускается с Верификатора Приложения, но можно уже знать это.)

можно также попытаться отладить с Windbg и различным использованием! команда "кучи".

MSN

1
ответ дан Mat Noguchi 24 November 2019 в 18:32
поделиться

Это находится в низких условиях памяти? Раз так это могло бы быть настолько новым, возвращается NULL вместо того, чтобы бросить станд.:: bad_alloc. Более старый VC++ компиляторы правильно не реализовали это. Существует статья [приблизительно 114] сбои выделения памяти Прежней версии катастрофический отказ STL приложения, созданные с VC6.

3
ответ дан CloudyMarble 24 November 2019 в 18:32
поделиться

Очевидная случайность повреждения памяти очень походит на проблему синхронизации потока - ошибка воспроизводится в зависимости от скорости машины. Если объекты (блоки памяти) являются общими для потоками и синхронизацией (критический раздел, взаимное исключение, семафор, другой), примитивы не находятся на на класс (на объект, на класс) основание, то возможно прийти к ситуации, где класс (блок памяти) удален / освобожденный, в то время как используемый или использовал, после того, как удалено / освобожденный.

Как тест, для которого, Вы могли добавить примитивы синхронизации к каждому классу и методу. Это сделает Ваш код медленнее, потому что много объектов должны будут ожидать друг друга, но если это устранит повреждение "кучи", Ваша проблема повреждения "кучи" станет оптимизацией кода один.

3
ответ дан Ignas Limanauskas 24 November 2019 в 18:32
поделиться

Необходимо приняться за решение этой проблемы и с и со статическим анализом во время выполнения.

Для статического анализа рассматривают компиляцию с PREfast (cl.exe /analyze). Это обнаруживает не соответствовавший delete и delete[], переполнение буфера и хост других проблем. Будьте готовы, тем не менее, пробраться через многие килобайты предупреждения L6, особенно если Ваш проект все еще имеет L4 не зафиксированный.

PREfast доступен с Системой Команды Visual Studio и, , по-видимому , как часть Windows SDK.

4
ответ дан CloudyMarble 24 November 2019 в 18:32
поделиться

Нам довольно везло путем записи нашего собственного malloc и бесплатных функций. В производстве они просто называют стандарт malloc и свободный, но в отладке, они могут сделать то, что Вы хотите. У нас также есть простой базовый класс, который действительно только переопределяет новые и операторы delete для использования этих функций, тогда любой класс, который Вы пишете, может просто наследоваться тому классу. Если у Вас есть тонна кода, это может быть большое задание для замены вызовов к malloc и свободный к новому malloc, и свободный (не забывайте перевыделение!), но в конечном счете это очень полезно.

В книге Steve Maguire, Пишущий Твердый Код (настоятельно рекомендованный), существуют примеры материала отладки, как который можно сделать в этих стандартных программах:

  • Отслеживают выделения, чтобы найти, что утечки
  • Выделяют больше памяти, чем необходимые и помещенные маркеры вначале и конец памяти - во время свободной стандартной программы, можно удостовериться, что эти маркеры все еще там
  • memset память с маркером на выделении (чтобы найти, что использование неинициализированной памяти) и на свободном (находит использование free'd памяти)

, Другая хорошая идея к никогда , вещи использования как strcpy, strcat, или sprintf - всегда используют strncpy, strncat, и snprintf. Мы записали наши собственные версии их также, чтобы удостовериться, что мы не списываем конец буфера, и они поймали много проблем также.

7
ответ дан CloudyMarble 24 November 2019 в 18:32
поделиться

Запустите исходное приложение с ADplus -crash -pn appnename.exe, Когда проблема памяти откроется, Вы получите хороший большой дамп.

можно проанализировать дамп для расчета, какая ячейка памяти была повреждена. Если Вы удачливы, что память перезаписи является уникальной строкой, можно выяснить, куда она прибыла из. Если Вы не будете удачливы, необходимо будет вырыть в win32 "куча" и изобразить то, что было orignal характеристиками памяти. ("куча"-x могла бы помочь)

после знания то, что было смешано, можно сузить appverifier использование к специальным настройкам "кучи". т.е. можно определить то, что DLL Вы контролируете, или что размер выделения контролировать.

, Надо надеяться, этот будет ускорение контроль достаточно для ловли преступника.

, По моему опыту, мне никогда не был нужен полный режим верификатора "кучи", но я провел много времени, анализируя дамп (дампы) катастрофического отказа и просмотрев источники.

P.S.: можно использовать DebugDiag для анализа дампов. Это может указать DLL владение поврежденной "кучей" и предоставить Вам другую полезную подробную информацию.

8
ответ дан CloudyMarble 24 November 2019 в 18:32
поделиться

У меня есть те же проблемы в моей работе (мы также используем VC6 иногда). И нет никакого легкого решения для него. У меня есть только некоторые подсказки:

  • Попытка с автоматическими дампами катастрофического отказа на производственной машине (см. Самосвал Процесса ). Мой опыт говорит, что доктор Watson не прекрасен для дампа.
  • Удаляют весь выгода (...) от Вашего кода. Они часто скрывают серьезные исключения памяти.
  • Проверка Усовершенствованный Windows Debugging - существует много больших подсказок для проблем как Ваши. Я рекомендую это со всей своей основой.
  • , Если Вы используете STL попытка STLPort и отладочные сборки. Недопустимый итератор является адом.

Удача. Проблемы как Ваши берут нас месяцы для решения. Будьте готовы к этому...

11
ответ дан CloudyMarble 24 November 2019 в 18:32
поделиться

Вы попробовали старые сборки, но являетесь там основаниями, которые Вы не можете продолжать идти далее назад в истории репозитория и видеть точно, когда ошибка была представлена?

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

, Если можно узнать то, что точно причина CAN эта проблема, через Google и документацию исключений Вы получаете, возможно, который даст дальнейшее понимание на том, что искать в коде.

1
ответ дан Mike Stone 24 November 2019 в 18:32
поделиться

Как вы думаете, это состояние гонки? Несколько потоков совместно используют одну кучу? Можете ли вы предоставить каждому потоку частную кучу с помощью HeapCreate, тогда они могут работать быстро с HEAP_NO_SERIALIZE. В противном случае куча должна быть потокобезопасной, если вы используете многопоточную версию системных библиотек.

0
ответ дан 24 November 2019 в 18:32
поделиться

Пара предложений. Вы упомянули обильные предупреждения на W4 - я бы посоветовал потратить время на то, чтобы исправить ваш код, чтобы он компилировался чисто на уровне предупреждения 4 - это будет иметь большое значение для предотвращения трудноуловимых ошибок, которые трудно найти.

Во-вторых, для переключателя / analysis. - он действительно генерирует обильные предупреждения. Чтобы использовать этот переключатель в моем собственном проекте, я создал новый файл заголовка, который использовал #pragma warning, чтобы отключить все дополнительные предупреждения, генерируемые / анализировать. Затем, ниже по файлу, я включаю только те предупреждения, которые мне небезразличны. Затем используйте переключатель компилятора / FI, чтобы этот файл заголовка был включен первым во все ваши единицы компиляции. Это должно позволить вам использовать переключатель / analysis при управлении выходом

0
ответ дан 24 November 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: