Странная Ошибка сегментирования.

Модератор: Модераторы разделов

Ответить
MiK13
Сообщения: 1164
ОС: Linux Debian

Странная Ошибка сегментирования.

Сообщение MiK13 »

Решил почитать про Малоизвестные возможности и последние нововведения в языке C.
И увидел там "Листинг 6. Определение тактовой частоты процессора (файл extent.c)"
Загрузил архив с примерами lang_c_details.tgz (правда, для этого пришлось принять соглашение). Распаковавл make выдал кучу предупреждений. В основном из-за несоответствия типов. Исправил это, заменив %d на %zd. Но меня заинтересовала программа extent, которая среди прочего выводит и тактовую частоту процессора, читая какой-то счётчик с помощью функции (в модуле t030t.c)

Код: Выделить всё

static unsigned long long rdtsc( void ) {
   unsigned long long int x;
   asm volatile ( "rdtsc" : "=A" (x) );      // команда RDTSC
   return x;
}

Запускаю. Иногда выдаёт реальную частоту (3.512 Ghz), а иногда -- что-то несуразное: 18446744072.926 Ghz
Считается она так:

Код: Выделить всё

   time_t t1, t2;
   unsigned long long cf=0, cs=0;
   TITLE( "ассемблерные вставки" );
   time( &t1 );
   while( t1 == time( &t2 ) ) cf  = rdtsc(); // начало очередной секунды
   while( t2 == time( &t1 ) ) cs  = rdtsc(); // завершение этой секунды
   printf( "тактовая частота процессора %.3f Ghz\n (%llu - %llu)\n",(double)( cs - cf ) / 1.E9 , cs, cf);

Оказалось, что иногда cs меньше, чем cf.
Решил посмотреть, как меняется значение счётчика при последовательном считывании. Добавил после этого код:

Код: Выделить всё

  for(i=0;i<100;i++) {
//    printf("m[%d] = ",i); fflush(stdout);
    m[i] = rdtsc();
//    printf("%llu\n",m[i]);
  }

Запускаю -- после выдачи частоты получаю
Ошибка сегментирования
Но если раскомментировать строки с printf, то программа работает.
При этом средняя разность между соседними значениями составляет примерно 37785 при выводе на консоль (в иксах) и 2800 при записи stdout в файл.

Посмотрел Makefile -- увидел, что среди опций компилятора есть -O. Убрал. Программа отработала нормально. Средняя разность между соседними получениями значения счётчика составила примерно 40.
Но как оптимизация (причём, без указания значения) могла на это повлиять?

Система Debian Jessie, amd64, gcc version 4.9.2 (Debian 4.9.2-10)
Спасибо сказали:
MiK13
Сообщения: 1164
ОС: Linux Debian

Re: Странная Ошибка сегментирования.

Сообщение MiK13 »

Попробовал проверить на работе (Debian 7) -- не вылетает даже при компиляции с оптимизацией. При этом почти стабильно значение увеличивается на 36.
Сейчас попробовал дома посмотреть, что даёт оптимизация.
Оставил в функции только цикл с занесением знаяения функции rdtsc(). Компилировал, добавив -S. два раза -- с -O и без. Разница очень большая. Язык ассемблера я почти не знаю, но впечатление, что компилятор вместо вызова функции rdtsc() просто вставил инструкцию rdtsc.
Спасибо сказали:
Ответить