Jump to content

    
Sign in to follow this  
Harvester

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

Recommended Posts

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

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, ...)

 

Edited by Harvester

Share this post


Link to post
Share on other sites
5 минут назад, Harvester сказал:

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

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

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

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

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

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

Share this post


Link to post
Share on other sites
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 - предлагаете угадывать?

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
19 минут назад, Harvester сказал:

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

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

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

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

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

Share this post


Link to post
Share on other sites
10 minutes ago, Сергей Борщ said:

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

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

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

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

Share this post


Link to post
Share on other sites
59 минут назад, Harvester сказал:

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

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

Share this post


Link to post
Share on other sites
14 hours ago, Сергей Борщ said:

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

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

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

Share this post


Link to post
Share on other sites
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);

 

 

Share this post


Link to post
Share on other sites
2 часа назад, Harvester сказал:

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this