Есть ли способ в gcc или clang (или любом другом компиляторе) выплевывать информацию о том, есть ли в структуре дыры (выравнивание памяти) в ней?
Спасибо.
PS: Если есть другой способ сделать это, пожалуйста, сообщите мне.
Есть ли способ в gcc или clang (или любом другом компиляторе) выплевывать информацию о том, есть ли в структуре дыры (выравнивание памяти) в ней?
Спасибо.
PS: Если есть другой способ сделать это, пожалуйста, сообщите мне.
Вы можете использовать pahole
для вывода информации о дырах в структурах и при необходимости попытаться их запаковать.
Вы можете прочитать "Poke-a-hole and friends" и объявление pahole для получения дополнительной информации
Я не знаю никакого автоматического инструмента, но это может быть полезным примером:
#include <stddef.h>
struct test {
typea a;
typeb b;
typec c;
};
int gapB = offsetof(struct test, b) - (offsetof(struct test, a) + sizeof(typea));
int gapC = offsetof(struct test, c) - (offsetof(struct test, b) + sizeof(typeb));
printf("Gap of b:%d/n", gapB);
printf("Gap of c:%d/n", gapC);
*Примечание: вам придется сделать это для каждых двух участников в вашем застревании.
Это можно сделать с помощью FlexeLint/PClint от Gimpel.
$ cat tst.c
int main (void)
{
struct {
char c;
double d;
short s;
} f = { 1, 2.0, 3 };
return f.c;
}
Он сообщит
$ flexelint -w1 +e95? tst.c
FlexeLint for C/C++ (Unix) Vers. 9.00L, Copyright Gimpel Software 1985-2014
--- Module: tst.c (C)
_
double d;
tst.c 5 Note 958: Padding of 7 byte(s) is required to align member on 8 byte
boundary
_
} f = { 1, 2.0, 3 };
tst.c 7 Note 959: Nominal struct size (18 bytes) is not an even multiple of
the maximum member alignment (8 bytes)
tst.c 7 Note 958: Padding of 6 byte(s) is required to align end of struct on
8 byte boundary
Вы можете изучить этот вопрос, написав тестовый код для конкретного struct
, используя sizeof
и &
; если sizeof
n-й член не равен адресу следующего члена минус адрес этого члена, есть дыра.
Один из способов найти такие дыры без анализа исходного кода и добавления к нему проверок (используя offsetof() и т.п.) состоит в том, чтобы извлечь информацию о символах/отладке из файлов объектов/исполняемых файлов/символов с помощью какого-либо инструмента и посмотреть на определить структуры и элементы в них, их смещения и размеры и посмотреть, все ли сходится. Однако союзы все усложнят.
pahole
и другие
- person underscore_d; 12.03.2016
Вы можете обнаружить такие «дыры» с помощью макроса offsetof
:
#include <stddef.h>
struct test {
char a;
int b;
};
...
printf("%zu", offsetof(struct test, b));
Если это напечатает больше, чем 1
, b
очевидно требует выравнивания, и компилятор создает промежуток между ними.
Очевидно, это происходит во время выполнения, а не во время компиляции, но вы можете написать сценарий, который создает аналогичный исходный файл, компилирует и запускает его перед остальной частью вашего проекта, а затем, на основе вывода, вы принимаете дальнейшие решения о том, как построить свой проект.
Я не думаю, что какой-либо компилятор предоставляет возможность уведомить вас об этом.
Вам нужен синтаксический анализатор, который понимает структуры c/c++ и включает в себя необходимые включаемые файлы.
Как ответил @roee-gavirel, я думаю, что более простым решением является создание тестовой программы для распечатки смещений.
#include <stdio.h>
#include <stddef.h>
typedef struct tData {
long id; /* 8 bytes */
char name[8]; /* 8 bytes */
float salary; /* 4 bytes */
} tData;
tData d;
int main()
{
size_t s_tData = sizeof(tData);
size_t s_id = sizeof(d.id);
size_t s_name = sizeof(d.name);
size_t s_salary = sizeof(d.salary);
printf("sizeof(tData) = %zu\n\n", sizeof(d));
printf("'id' is at = %3zu occupies %zu bytes\n",
offsetof(tData, id), s_id);
printf("'name' is at = %3zu occupies %zu bytes\n",
offsetof(tData, name), s_name);
printf("'salary' is at = %3zu occupies %zu bytes\n",
offsetof(tData, salary), s_salary);
printf("\n");
if (s_tData != s_id + s_name + s_salary)
printf("There is/are holes\n");
return 0;
}