Ochkarik
|
|
« : 19-01-2017 16:43 » |
|
народ, дивлюсь и не понимаю где искать: быстро собирал демо проект копипастом кусков из других проектов C++/WinAPI под студию 2015. ну косяков полно, начал под отладчиком студии ползать построчно. и началось.... в коде строчка lpp->Addr.Num = 2; а после ее исполнения отладчик показывает что двойкой стало следующее поле структуры Addr! куда копать не соображу? как такое вообще может быть?
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Ochkarik
|
|
« Ответ #1 : 19-01-2017 16:46 » |
|
PS почему то с выравниванием что то не срослось... выставил 4 байта стало работать.
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Ochkarik
|
|
« Ответ #2 : 19-01-2017 16:50 » |
|
у меня есть структуры которые на 4 выравнены #pragma pack(push,4) .... #pragma pack(pop) но вроде всегда раньше работало нормально... и по факту и отображение.
|
|
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Ochkarik
|
|
« Ответ #3 : 19-01-2017 17:01 » |
|
PPS не, кажись пропустил кое где... но все равно не должно быть такого же? нет? чтоб в отладчике неверно отображалось. это ж важно только когда межпроцессами обмен.. или DLL .... тут это есть но после. ошибка отображения возникает до того как обращение к DLL выравненной на 4 байта произошло...
|
|
« Последнее редактирование: 19-01-2017 17:19 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Aether
|
|
« Ответ #4 : 19-01-2017 20:32 » |
|
lpp->Addr.Num = 2; а после ее исполнения отладчик показывает что двойкой стало следующее поле структуры Addr! куда копать не соображу? как такое вообще может быть? Протестировать отдельно можно? 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 »
|
Записан
|
|
|
|
Джон
просто
Администратор
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."
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 20-01-2017 04:53 » |
|
Ochkarik, по умолчанию студии в проекте выравнивание на 4 (в настройках проекта то есть)
Также искани по всему проекту "#pragma pack" (возможно, регуляркой, чтобы учесть пробелы "#pragma(\s)+pack" )
и в результате поиска уточни, что везде есть открывающая и закрывающая прагма push/pop (они могут быть и вложенные, кстати)
Если такая пАрность пропущена где-то, то описанные чудеса с выравниванием могут происходить - в A.cpp будет одно, а в B.cpp другое для одной и той же структуры
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #7 : 20-01-2017 10:23 » |
|
Леш, по дефолту всегда было 8 байт) парность на месте. на свежую голову другой косяк нашел: один заголовочный файл без pragma был включен в два других заголовочных файла c разным выравниванием объявленным при помощи #pragma(( и разные исполняемые cpp включали разные версии получается. накопипастил не глядя. но вообще как-то неаккуратно получается и в исходном проекте было...
|
|
« Последнее редактирование: 20-01-2017 10:34 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Ochkarik
|
|
« Ответ #8 : 20-01-2017 10:25 » |
|
помогло чтение MSDN и директива #pragma pack( show ) отличная директива - показывает в output при компиляции текущее значение выравнивания. на ту структуру на которую наткнулся - увидел два раза включение и два раза разные значения выравнивания. а вывод такой, что не надо было #pragma pack(push, 4) до #include ставить! PS честно говоря вообще перестал понимать как оно раньше работало у меня там и виндовые хедеры включались... видимо они совсем правильно написаны, для идиотов.
|
|
« Последнее редактирование: 20-01-2017 10:30 от Ochkarik »
|
Записан
|
RTFM уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 20-01-2017 13:01 » |
|
Ochkarik, да нет, у меня всегда 4 байта по умолчанию было, правда студии 6 и 9, более новые не трогал а в pragma pack нужно оборачивать конкретно объявление структуры/класса, а не весь файл. Тогда и не наткнёшься никогда на такое ) то есть #pragma pack(push,1) struct ... { ... }; #pragma pack(pop)
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #10 : 20-01-2017 13:37 » |
|
Выравнивание еще зависит от типа и порядка расположения элементов в структуре. #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
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
RXL
|
|
« Ответ #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 Этот пример намекает, что это без фикированного выравнивания будет работать неправильно: 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
Молодой специалист
Offline
|
|
« Ответ #13 : 23-01-2017 07:17 » |
|
Прошу прощения, что вмешиваюсь, по-моему 16 байт на x86-64 компилятор выставляет из-за SSE. Насколько я помню, в данной архитектуре, в отличии от x86, SSE является обязательным, и чтобы не было проблем с доступа к невыравненными данным устанавливается такое выравнивание.
|
|
|
Записан
|
|
|
|
Ochkarik
|
|
« Ответ #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 уже хоть раз наконец! :[ ну или хотя бы STFW...
|
|
|
RXL
|
|
« Ответ #15 : 23-01-2017 17:59 » |
|
Я бы еще для таких выровненных структур тесты добавлял на позицию каждого поля.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|