Перейти к содержанию
    

Непонятное поведение программы

Столкнулся с такой странностью. В результате выполнения кода

struct statfs fs;
if (statfs(DREC_STORAGE_DEF, &fs) == 0)
{
	msg(LOG_DEBUG, "f_blocks=%u\n", fs.f_blocks);
	msg(LOG_DEBUG, "f_bfree=%u\n", fs.f_bfree);
	msg(LOG_DEBUG, "f_bavail=%u\n", fs.f_bavail);
	size_t blocks = fs.f_blocks;
	size_t bfree  = fs.f_bfree;
	size_t bavail = fs.f_bavail;
	msg(LOG_DEBUG, "f_blocks=%u\n", blocks);
	msg(LOG_DEBUG, "f_bfree=%u\n", bfree);
	msg(LOG_DEBUG, "f_bavail=%u\n", bavail);
}

получаю такой вывод:

09:47:39.949371 f_blocks=0
09:47:39.950237 f_bfree=0
09:47:39.950361 f_bavail=0
09:47:39.950421 f_blocks=103705
09:47:39.950481 f_bfree=99962
09:47:39.950540 f_bavail=99962

Т.е. при выводе непосредственно полей структуры получаем нули. Как такое может быть?

Если что, функция msg() - просто обертка над printf/fprintf:

void msg(int log_level, const char* mes, ...)

 

Изменено пользователем Harvester

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, Harvester сказал:

Т.е. при выводе непосредственно полей структуры получаем нули. Как такое может быть?

Посмотреть на результат компиляции (ассемблер) - пробовали?

5 минут назад, Harvester сказал:

Если что, функция msg() - просто обертка над printf/fprintf:

Видимо - кривая "обёртка"?

И что такое fs - предлагаете угадывать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 minutes ago, jcxz said:

Посмотреть на результат компиляции (ассемблер) - пробовали?

Еще нет. Не могу понять, как сгенерировать листинг :(

24 minutes ago, jcxz said:

Видимо - кривая "обёртка"?

void msg(int log_level, const char* mes, ...)
{
    va_list arg;
    struct timeval tv;
    struct tm* tm = NULL;

    if (log_level > logLevelMax)
        return;

    gettimeofday(&tv, NULL);
    tm = localtime(&tv.tv_sec);
    fprintf(_file4log, "%02u:%02u:%02u.%06lu ", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);

    va_start(arg, mes);
    vfprintf(_file4log, mes, arg);
    va_end(arg);
}

Что тут может быть кривого?

26 minutes ago, jcxz said:

И что такое fs - предлагаете угадывать?

Просто структура. Обновил код.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, xvr said:

Прототип msg в месте вызова виден?

Да

Получил ассемблерный листинг.

	addi 0,31,152	 # tmp235,,
	lis 9,.LC22@ha	 # tmp236,
	la 3,.LC22@l(9)	 #,, tmp236
	mr 4,0	 #, tmp235
	bl statfs64	 #
	mr 0,3	 # D.6778,
	cmpwi 7,0,0	 #, tmp237, D.6778
	bne 7,.L48	 #
.LBB9:
	.loc 2 382 0
	lwz 9,160(31)	 # fs.f_blocks, D.6781		r9  <- fs.f_blocks.hi
	lwz 10,164(31)	 # fs.f_blocks, D.6781		r10 <- fs.f_blocks.lo
	li 3,10	 #,					r3  <- LOG_DEBUG
	lis 0,.LC23@ha	 # tmp238,
	addic 4,0,.LC23@l	 #, tmp238,		r4  <- адрес строки
	mr 5,9	 #, D.6781				r5  <- r9  (fs.f_blocks.hi)
	mr 6,10	 # tmp5, D.6781				r6  <- r10 (fs.f_blocks.lo)
	crxor 6,6,6					r6  <- 0
	bl msg	 #					msg()
	.loc 2 385 0
	lwz 9,160(31)	 # fs.f_blocks, D.6782		r9  <- fs.f_blocks.hi
	lwz 10,164(31)	 # fs.f_blocks, D.6782		r10 <- fs.f_blocks.lo
	stw 10,12(31)	 # blocks, D.6782		12(31) <- r10 (blocks = fs.f_blocks.lo)
	.loc 2 388 0
	li 3,10	 #,					r3  <- LOG_DEBUG
	lis 0,.LC23@ha	 # tmp239,
	addic 4,0,.LC23@l	 #, tmp239,		r4  <- адрес строки
	lwz 5,12(31)	 # blocks,			r5  <- 12(31) (blocks)
	crxor 6,6,6					r6  <- 0
	bl msg	 #					msg()
.L48:

Получается, что а) поля структуры fs 64-битные и б) VA_ARGS некорректно работает с 64-битными значениями

Чуда в очередной раз не произошло :D

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 минут назад, Harvester сказал:

и б) VA_ARGS некорректно работает с 64-битными значениями

Ну хорошо хоть не Петров с Бошировым виноватыми назначены.

6 часов назад, Harvester сказал:

msg(LOG_DEBUG, "f_bfree=%u\n", fs.f_bfree);

Позволю себе поинтересоваться, а переменную какого типа вы тут просили напечатать (%u)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 minutes ago, Сергей Борщ said:

Позволю себе поинтересоваться, а переменную какого типа вы тут просили напечатать (%u)?

А слона-то я и не заметил ))))

Замена модификатора на %llu решило проблему. Пункт б) вычеркиваем - сам дурак.

Приношу извинения разработчикам компилятора и, на всякий случай, Петрову с Бошировым.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

59 минут назад, Harvester сказал:

Получается, что а) поля структуры fs 64-битные и б) VA_ARGS некорректно работает с 64-битными значениями

Поэтому я и спрашивал "что такое fs?" То же самое касается и всех прочих структур и функций, которые вы выкладываете. Думаете тут форум ясновидящих, умеющих угадывать что там внутри вы понаписали?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 hours ago, Сергей Борщ said:

Позволю себе поинтересоваться, а переменную какого типа вы тут просили напечатать (%u)?

И все равно непонятно.

Пусть у меня переменная uint64_t. Почему же модификатор %u выводит 0, хотя значение, содержащееся в переменной, укладывается в диапазон uint32_t? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Harvester сказал:

Почему же модификатор %u выводит 0, хотя значение, содержащееся в переменной, укладывается в диапазон uint32_t? 

Я ожидал этого вопроса :biggrin: (точнее, он у меня тоже вчера возник). Думаю, это происходит потому, что параметры передаются через стек. Процессор у вас с маленькими индейцами, на стек кладется сначала младшее слово, потом старшее (в котором нули). При выводе со стека берется и выводится верхнее слово (с нулями). Можно предположить, что если бы вы выводили два значения за один вызов printf() - вы увидели бы вместо первого числа ноль, вместо второго - значение младшего слова первой переменной. 

15 часов назад, Harvester сказал:

Замена модификатора на %llu решило проблему

В <inttypes.h> есть специальные определения PRIu64 для вывода 64-битных значений. Их использование предпочтительно, если один и тот же исходник предполагается компилировать для разных платформ или разными компиляторами. Не у каждого компилятора для вывода 64-битных значений будет использоваться "%llu", а в этом файле PRIu64 будет содержать подходящее для данного компилятора определения. Строка будет выглядеть так:

msg(LOG_DEBUG, "f_blocks=" PRIu64 "\n", fs.f_blocks);

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Harvester сказал:

Пусть у меня переменная uint64_t. Почему же модификатор %u выводит 0, хотя значение, содержащееся в переменной, укладывается в диапазон uint32_t? 

Потому что в форматной строке printf()-у вы сообщаете, что передадите ему 4 слова, а передаёте больше. И какой из передаваемых аргументов куда попадёт - зависит от размерностей аргументов и от порядка записи аргументов в стек (от начала к концу или наоборот).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...