Как отладить ошибки повреждения "кучи"?

Попробуйте это

((ViewPager) container)
                .setOnPageChangeListener(new OnPageChangeListener() {
                    @Override
                    public void onPageSelected(int position) {
                        Log.i("TAG", "pos::" + position);

                    }
                    @Override
                    public void onPageScrollStateChanged(int state) {
                        // TODO Auto-generated method stub                            
                           int currentPage = pager.getCurrentItem();
                           Log.i("TAG", "currentPage::" + currentPage);
                           Log.i("TAG", "currentState::" + currentState);
                           Log.i("TAG", "previousState::" + previousState);
                           if (currentPage == 4 || currentPage == 0) {
                            previousState = currentState;
                            currentState = state;
                            if (previousState == 1 && currentState == 0) {
                             pager.setCurrentItem(currentPage == 0 ? 4 : 0);
                            }
                           }

                    }

                    @Override
                    public void onPageScrolled(int arg0, float arg1,
                            int arg2) {
                        // TODO Auto-generated method stub

                    }
                });

        return

Это должно быть размещено внутри

 @Override
    public Object instantiateItem(final View container, int position) {}
162
задан Peter Mortensen 24 January 2013 в 20:21
поделиться

9 ответов

Application Verifier в сочетании с Инструменты отладки для Windows - потрясающая установка. Вы можете получить и то, и другое в составе комплекта драйверов Windows или более легкого Windows SDK . (Узнал о Application Verifier при исследовании более раннего вопроса о проблеме повреждения кучи .) Я также использовал BoundsChecker и Insure ++ (упомянутые в других ответах) в прошлом, хотя был удивлен, насколько много функциональности было в Application Verifier.

Electric Fence (он же «efence»), dmalloc , valgrind и т. д. - все это заслуживает упоминания, но большинство из них намного проще запустить под * nix, чем под Windows. Valgrind смехотворно гибок: я отлаживал большое серверное программное обеспечение с множеством проблем с кучей, используя его.

Когда все остальное терпит неудачу, вы можете предоставить своему собственному глобальному оператору new / delete и malloc / calloc / realloc перегрузки - как это сделать, будет немного отличаться в зависимости от компилятора и платформы - и это будет немного инвестиции - но они могут окупиться в долгосрочной перспективе. Список желаемых функций должен быть знаком по dmalloc и electricfence, а также по удивительно отличной книге Writing Solid Code :

  • sentry values ​​: оставьте немного больше места до и после каждого выделения, соблюдая максимальное выравнивание требование; заполнить магическими числами (помогает отловить переполнение и опустошение буфера, а также случайный «дикий» указатель)
  • alloc fill : заполните новые выделения волшебным значением, отличным от 0 - Visual C ++ уже сделает это за вас в Отладочные сборки (помогает выявить использование неинициализированных переменных)
  • free fill : заполнить освободившуюся память магическим значением, отличным от 0, предназначенным для запуска segfault, если он разыменован в большинстве случаев (помогает поймать оборванные указатели)
  • отложено освобождение : не возвращать освобожденную память в кучу некоторое время , держите его свободным заполненным, но не доступным (помогает поймать больше висячих указателей, улавливает близкие двойные освобождения)
  • отслеживание : возможность записывать, где было выполнено выделение, иногда может быть полезна

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


Если вас интересует больше причин для перегрузки этих функций / операторов распределения, возьмите взгляните на мой ответ на вопрос «Есть ли причина для перегрузки глобального оператора new и delete?» ; бесстыдная самореклама в сторону,

126
ответ дан 23 November 2019 в 21:22
поделиться

Помимо поиска инструментов, подумайте о поиске вероятного виновника. Есть ли какой-либо компонент, который вы используете, возможно, написанный не вами, который, возможно, не был разработан и протестирован для работы в многопоточной среде? Или просто тот, о котором вы не знаете, работал в такой среде.

В последний раз это случилось со мной, это был собственный пакет, который годами успешно использовался из пакетных заданий. Но впервые в этой компании он использовался из веб-службы .NET (которая является многопоточной). Вот и все - они солгали, что код является потокобезопасным.

1
ответ дан 23 November 2019 в 21:22
поделиться

Если эти ошибки возникают случайно, существует высокая вероятность того, что вы столкнулись с гонками данных. Пожалуйста, проверьте: модифицируете ли вы указатели разделяемой памяти из разных потоков? Intel Thread Checker может помочь обнаружить такие проблемы в многопоточной программе.

3
ответ дан 23 November 2019 в 21:22
поделиться

Какие вещи могут вызывать эти ошибки?

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

Как отладить их?

Используйте инструмент, который добавляет автоматическую проверку границ вашего исполняемого файла: например, valgrind в Unix, или инструмент, подобный BoundsChecker (Википедия предлагает также Purify и Insure ++) в Windows.

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

Другим возможным средством / инструментом отладки может быть HeapAgent MicroQuill.

8
ответ дан 23 November 2019 в 21:22
поделиться

Вы можете обнаружить множество проблем с повреждением кучи, включив Page Heap для своего приложения. Для этого вам нужно использовать gflags.exe, который входит в состав Debugging Tools For Windows

Запустите Gflags.exe и в параметрах файла изображения для исполняемого файла отметьте опцию «Включить кучу страниц».

Теперь перезапустите исполняемый файл и подключитесь к отладчику. При включенной куче страницы приложение будет взламывать отладчик при любом повреждении кучи.

35
ответ дан 23 November 2019 в 21:22
поделиться

Лучший инструмент, который я считал полезным и с которым я работал каждый раз, - это проверка кода (с хорошими рецензентами кода).

Кроме проверки кода, я сначала попробую Page Heap ]. Настройка Page Heap занимает несколько секунд и, если повезет, может выявить вашу проблему.

Если не повезло с Page Heap, загрузите Debugging Tools for Windows от Microsoft и научитесь использовать WinDbg. Извините, не могу дать вам более конкретной помощи, но отладка повреждения многопоточной кучи - это больше искусство, чем наука. Погуглите "повреждение кучи WinDbg", и вы должны найти много статей по этой теме.

5
ответ дан 23 November 2019 в 21:22
поделиться

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

Если вы хотите найти ошибку быстро, не проверяя каждый инструкция, которая обращается к памяти блок, вы можете установить указатель памяти к недопустимому значению после освобождения block:

 #ifdef _DEBUG // определить доступ к освобожденной памяти
#undef бесплатно
#define free (p) _free_dbg (p, _NORMAL_BLOCK); * (число *) & p = 0x666;
#endif
8
ответ дан 23 November 2019 в 21:22
поделиться

Какие типы функций распределения вы используете? Недавно я столкнулся с аналогичной ошибкой, используя функции распределения в стиле Heap *.

Оказалось, что я по ошибке создавал кучу с параметром HEAP_NO_SERIALIZE . По сути, это заставляет функции кучи работать без обеспечения безопасности потоков. Это улучшение производительности при правильном использовании, но никогда не должно использоваться, если вы используете HeapAlloc в многопоточной программе [1]. Я упоминаю об этом только потому, что в вашем сообщении упоминается, что у вас есть многопоточное приложение. Если вы где-то используете HEAP_NO_SERIALIZE, удалите его, и это, скорее всего, решит вашу проблему.

[1] Есть определенные ситуации, когда это допустимо, но требует сериализации вызовов кучи *, что обычно не относится к многопоточным программам.

3
ответ дан 23 November 2019 в 21:22
поделиться
13
ответ дан 23 November 2019 в 21:22
поделиться
Другие вопросы по тегам:

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