Ошибка SIGSEGV для fpc_dynarray_length

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ошибка SIGSEGV для fpc_dynarray_length

Сообщение CRobin » 23.10.2016 21:10:25

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

Код: Выделить всё
fpc_dynarray_length
000000000040B960 4885c9                   test   %rcx,%rcx
000000000040B963 740d                     je     0x40b972 <fpc_dynarray_length+18>
000000000040B965 4883e910                 sub    $0x10,%rcx
[b]000000000040B969 488b4108                 mov    0x8(%rcx),%rax[/b]
000000000040B96D 48ffc0                   inc    %rax
000000000040B970 eb0a                     jmp    0x40b97c <fpc_dynarray_length+28>
000000000040B972 48b80000000000000000     movabs $0x0,%rax
000000000040B97C c3                       retq   
000000000040B97D 0000                     add    %al,(%rax)
000000000040B97F 00                       add    %cl,-0x7b(%rax)


Объясните, в чем может быть проблема? Если я правильно понимаю, длинна динамического массива записывается в первые 4 байта перед нулевым элементом массива, тогда что происходит в этой функции и откуда берется ошибка записи в память при ее выполнении? Спасибо.
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Ошибка SIGSEGV для fpc_dynarray_length

Сообщение runewalsh » 23.10.2016 22:42:20

Ты повредил память, случайно перезаписав переменную с массивом, или разместил её в неинициализированной области (любая память, выделенная не конструкторами/New/SetLength). Например,
Код: Выделить всё
type
   TBlock = record
      a: array of integer;
   end;

var
   p: ^TBlock;

begin
   p := GetMem(sizeof(TBlock)); // в других ситуациях компилятор автоматически зануляет автоуправляемые типы,
                                // но здесь память не инициализирована

   SetLength(p^.a, 20);         // ← поэтому это может упасть

   FreeMem(p);                  // ← аналогично, компилятор не может отследить освобождение,
                                // поэтому здесь утечёт аллокация для a, если SetLength всё же сработала
end;

Правильно:
Код: Выделить всё
   p := GetMem(sizeof(TBlock));
   System.Initialize(p^);       // Это занулит автотипы. Вызовы new, SetLength и т. п. разворачиваются в GetMem + Initialize.

   SetLength(p^.a, 20);         // OK

   System.Finalize(p^);         // освобождает автотипы, dispose() = Finalize + FreeMem
   FreeMem(p);                  // OK
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Ошибка SIGSEGV для fpc_dynarray_length

Сообщение CRobin » 24.10.2016 00:56:04

runewalsh правильно ли я понимаю, что fpc_dynarray_length выполняется когда я вызываю Length?
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Ошибка SIGSEGV для fpc_dynarray_length

Сообщение zub » 24.10.2016 01:25:26

>>правильно ли я понимаю, что fpc_dynarray_length выполняется когда я вызываю Length?
не факт, думаю может вызываться и при других операциях с динмассивом.

>>в различных частях приложения, которую не показывает отладчик.
Откройте стек вызовов и глянте последний адрес принадлежащий вашему коду. Также стоит выключить оптимизацию.
Но это будет место вылета, а не место где повреждается куча.
Саму ошибку можно будет поправить
1 - устранив всю ругань heaptrc
2 - устранив всю ругань valgrind
3 - отладкой
Варианты перечислены в порядке возрастания сложности и вероятности нахождения ошибки
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Ошибка SIGSEGV для fpc_dynarray_length

Сообщение runewalsh » 24.10.2016 01:44:18

Э-ээ, а вообще у меня (fpc 3.0.0) fpc_dynarray_length никогда не вызывается, даже на 0 уровне оптимизации Length разворачивается в проверку на пустой массив, чтение (data_ptr - sizeof(SizeInt))^ и добавление единички (FPC хранит значение High). Посмотри на ассемблерный листинг какого-нибудь кода с Length, если у тебя так же, то, может, повредил стек и случайно прыгнул на неиспользуемую fpc_dynarray_length, или используешь ассемблерную вставку, её вызывающую, у меня нет других вариантов.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 20

Рейтинг@Mail.ru