Сегфоэлектрические ограждения в Malloc

У меня довольно сложная программа, занимающая много места в памяти, и сегодня она неожиданно начала работать с ошибками странным образом, что GDB не может точно определить местоположение. Подозревая где-то повреждение памяти, я связал это с Electric Fence, но я озадачен тем, что он говорит мне:

ElectricFence Exiting: mprotect() failed:                                   
Program received signal SIGSEGV, Segmentation fault.                        
__strlen_sse2 () at ../sysdeps/i386/i686/multiarch/strlen.S:99              
99      ../sysdeps/i386/i686/multiarch/strlen.S: No such file or directory. 
        in ../sysdeps/i386/i686/multiarch/strlen.S                          

#0  __strlen_sse2 () at ../sysdeps/i386/i686/multiarch/strlen.S:99  
#1  0xb7fd6f2d in ?? () from /usr/lib/libefence.so.0                
#2  0xb7fd6fc2 in EF_Exit () from /usr/lib/libefence.so.0           
#3  0xb7fd6b48 in ?? () from /usr/lib/libefence.so.0                
#4  0xb7fd66c9 in memalign () from /usr/lib/libefence.so.0          
#5  0xb7fd68ed in malloc () from /usr/lib/libefence.so.0            
#6  <and above are frames in my program>

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

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

EF_PROTECT_FREE=1
EF_PROTECT_BELOW=1
EF_ALIGNMENT=64
EF_ALIGNMENT=4096

Последние два не имели абсолютно никакого эффекта.

Первый из них изменил части стекового фрейма, которые есть в моей программе (где в моей программе выполнялся, когда malloc вызывался фатально), но с идентичными фреймами после ввода malloc.

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

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

Обновление: я обнаружил несколько мест, где указывается, что сообщение: " mprotect() не удалось: невозможно выделить память" означает, что на машине недостаточно памяти. Но я не вижу части "Не удается выделить память", и ps говорит, что я использую только 15% памяти. С таким небольшим распределением (4k+32) это может быть проблемой?

1 ответ

Решение

Я просто потратил несколько часов на ту же проблему. Оказывается, это связано с настройкой в ​​/proc/sys/vm/max_map_count

Из документации ядра: "Этот файл содержит максимальное количество областей карты памяти, которое может иметь процесс. Области карты памяти используются в качестве побочного эффекта вызова malloc непосредственно mmap и mprotect, а также при загрузке разделяемых библиотек.

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

Таким образом, вы можете "поймать" этот файл, чтобы увидеть, на что он установлен, и затем вы можете "вставить" в него большее число. Пример: echo 165535 > /proc/sys/vm/max_map_count

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

Другие вопросы по тегам