Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: чудеса VS2015  (Прочитано 20545 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 19-01-2017 16:43 » new

народ, дивлюсь и не понимаю где искать:
быстро собирал демо проект копипастом кусков из других проектов C++/WinAPI под студию 2015.
ну косяков полно, начал под отладчиком студии ползать построчно.
и началось....
в коде строчка
Код: (C++)
lpp->Addr.Num = 2;
а после ее исполнения отладчик показывает что двойкой стало следующее поле структуры Addr!

куда копать не соображу? как такое вообще может быть?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 19-01-2017 16:46 » 

PS почему то с выравниванием что то не срослось... выставил 4 байта стало работать.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 19-01-2017 16:50 » 

у меня есть структуры которые на 4 выравнены
Код: (C++)
#pragma pack(push,4)
....
#pragma pack(pop)
но вроде всегда раньше работало нормально... и по факту и отображение.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 19-01-2017 17:01 » 

PPS не, кажись пропустил кое где... но все равно не должно быть такого же? нет? чтоб в отладчике неверно отображалось.
это ж важно только когда межпроцессами обмен.. или DLL ....
тут это есть но после. ошибка отображения возникает до того как обращение к DLL выравненной на 4 байта произошло...
« Последнее редактирование: 19-01-2017 17:19 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 19-01-2017 20:32 » 

Код: (C++)
lpp->Addr.Num = 2;
а после ее исполнения отладчик показывает что двойкой стало следующее поле структуры Addr!

куда копать не соображу? как такое вообще может быть?

Протестировать отдельно можно?
Код: (C)
typedef struct _A
{
   char B
   int C;
   long long D;
} A;

typedef struct _E
{
   long long F;
   A G;
} E, *pE;
...
E E1 = {...};
pE H = &E1;
...
// И поработать со значениями и выводом всей структуры
H->G.C = ...

Как был объявлен Addr и lpp? Может хитрый union?
« Последнее редактирование: 19-01-2017 20:36 от Aether » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 19-01-2017 20:47 » 

Какая студия? Какой апдейт (актуальный 3)?
Какой тип проекта? Какая целевая платформа?
ну и тд.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 20-01-2017 04:53 » 

Ochkarik, по умолчанию  студии в проекте выравнивание на 4 (в настройках проекта то есть)

Также искани по всему проекту "#pragma pack"  (возможно, регуляркой, чтобы учесть пробелы  "#pragma(\s)+pack" )

и в результате поиска уточни, что везде есть открывающая и закрывающая прагма push/pop (они могут быть и вложенные, кстати)

Если такая пАрность пропущена где-то, то описанные чудеса с выравниванием могут происходить - в A.cpp будет одно, а в B.cpp другое для одной и той же структуры
Записан

Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 20-01-2017 10:23 » 

Леш, по дефолту всегда было 8 байт)
парность на месте. на свежую голову другой косяк нашел:
один заголовочный файл без pragma был включен в два других заголовочных файла c разным выравниванием объявленным при помощи #pragma((
и разные исполняемые cpp включали разные версии получается.
накопипастил не глядя. но вообще как-то неаккуратно получается и в исходном проекте было...
« Последнее редактирование: 20-01-2017 10:34 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 20-01-2017 10:25 » 

помогло чтение MSDN и директива
Код: (C++)
#pragma pack(  show )
отличная директива - показывает в output при компиляции текущее значение выравнивания.  на ту структуру на которую наткнулся - увидел два раза включение и два раза разные значения выравнивания.

а вывод такой, что не надо было
Код: (C++)
#pragma pack(push, 4)
до #include ставить!

PS честно говоря вообще перестал понимать как оно раньше работало  Быть такого не может у меня там и виндовые хедеры включались... видимо они совсем правильно написаны, для идиотов.
« Последнее редактирование: 20-01-2017 10:30 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 20-01-2017 13:01 » 

Ochkarik, да нет, у меня всегда 4 байта по умолчанию было, правда студии 6 и 9, более новые не трогал

а в pragma pack нужно оборачивать конкретно объявление структуры/класса, а не весь файл. Тогда и не наткнёшься никогда на такое )

то есть

Код:
#pragma pack(push,1)
struct ...
{
...
};
#pragma pack(pop)
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 20-01-2017 13:37 » 

Выравнивание еще зависит от типа и порядка расположения элементов в структуре.

Код: (C)
#include <stdio.h>
#include <stdint.h>

//pragma pack(push,1)
struct x {
    char a;
    long double d;
    int b;
    uint64_t c;
};
//#pragma pack(pop)

int main() {
    printf("%p + %lu -> %p + %lu -> %p + %lu -> %p + %lu -> %lu\n",
        &(((struct x*)(void*)0)->a), sizeof(char),
        &(((struct x*)(void*)0)->d), sizeof(long double),
        &(((struct x*)(void*)0)->b), sizeof(int),
        &(((struct x*)(void*)0)->c), sizeof(uint64_t),
        sizeof(struct x)
    );
}

Попробуйте синхронно переставлять поля в struct x и соотв. строки в printf.

Это не C++! Это Си!

У меня gcc 5.4.0. Без pragma pack выравнивание зависит от типа. С pragma pack выравнивание фиксированное. Интересно, что у вас там, в VS.
« Последнее редактирование: 20-01-2017 15:33 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 20-01-2017 14:13 » 

Алексей++,  ключ Zp компилятора Packs structures on 8-byte boundaries (default).
https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(VC.Project.VCCLCompilerTool.StructMemberAlignment)&rd=true
наверное да. надо было каждую структуру, но это было лет десять назад если не больше, я тогда не думал на эту тему)))
RXL,
Попробуйте синхронно переставлять поля в struct x и соотв. строки в printf.

У меня gcc 5.4.0. Без pragma pack выравнивание зависит от типа. С pragma pack выравнивание фиксированное. Интересно, что у вас там, в VS.
при каком выравнивании переставлять? адреса будут зависеть от выравнивания структур)
в винде (то есть в VS) я думаю как и везде.
выравнивание задается ключом компилятора. по умолчанию 8 байт для каждого файла. студия по умолчанию ставит) если надо принудительно выровнять структуру - тогда через #pragma pack - у выбранных будет заданное выравнивание, у остальных - как компилятору сказали.
8 байт это вообще помоему типично для API винды. а вот структуры ядра x32 винды выровнены на 4 байта.
почему от типа? не только от типа но и от структуры.

PS кстати наткнулся https://msdn.microsoft.com/en-us/library/aa290049(v=vs.71).aspx

оказывается выравнивание стека компилятор может выставить сам? на 64 - 16 байт. на x86 - по разному?

« Последнее редактирование: 20-01-2017 14:25 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 20-01-2017 15:30 » 

В порядке a, b, c, d: (nil) + 1 -> 0x4 + 4 -> 0x8 + 8 -> 0x10 + 16 -> 32
В указанно выше примере (a, d, b, c): (nil) + 1 -> 0x10 + 16 -> 0x20 + 4 -> 0x28 + 8 -> 48

Тоже самое, но с pack 1:
(nil) + 1 -> 0x1 + 4 -> 0x5 + 8 -> 0xd + 16 -> 29
(nil) + 1 -> 0x1 + 16 -> 0x11 + 4 -> 0x15 + 8 -> 29

Этот пример намекает, что это без фикированного выравнивания будет работать неправильно:
Код: (C)
struct x {
  char a;
#ifdef __SOME_FLAG__
  long double d;
#else
  char[10] _pad_d;
#endif
  int b;
};
« Последнее редактирование: 20-01-2017 15:40 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #13 : 23-01-2017 07:17 » 

PS кстати наткнулся https://msdn.microsoft.com/en-us/library/aa290049(v=vs.71).aspx

оказывается выравнивание стека компилятор может выставить сам? на 64 - 16 байт. на x86 - по разному?
Прошу прощения, что вмешиваюсь, по-моему 16 байт на x86-64 компилятор выставляет из-за SSE. Насколько я помню, в данной архитектуре, в отличии от x86, SSE является обязательным, и чтобы не было проблем с доступа к невыравненными данным устанавливается такое выравнивание.
Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 23-01-2017 10:04 » 

RXL,
ну у меня выравнивание было необходимо так как происходит обмен структурами между процессами.
пример с формитированием через #ifdef.... почему будет не правильно работает? ровно как написано так и будет работать))) если без ошибок писать а не как я))))))

darkelf, возможно) я просто удивился что
"The compiler can determine, on some occasions, that dynamic 8-byte stack alignment would be beneficial—notably when there are double values on the stack." и далее по тексту.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 23-01-2017 17:59 » 

Я бы еще для таких выровненных структур тесты добавлял на позицию каждого поля.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines