2012-06-21 4 views
0

У меня есть библиотека C, хранящая записи с несколькими полями. Схема считывается из текстового файла, включая тип каждого поля в записи.Проверка времени выполнения C

Для упрощения для целей вопрос, представьте себе, у меня есть

typedef enum my_type_enum 
{ 
    INT32, //32-bit integer 
    MYSTRUCT, //some struct I have, details irrelevant 
    ... 
} my_type_enum; 

typedef struct my_var 
{ 
    my_type_enum typetag; 
    unsigned char* data; 
} my_var; 

my_var myrecord[numfields]; 

Файл схемы говорит ли каждое поле MyRecord следует провести int32_t или MyStruct. Моя библиотека читает файл схемы, и для каждого my_var в myrecord задает тег и выделяет нужное количество пространства для данных.

my_var непрозрачен и клиентские программы в основном используют для простых данных

void set(my_var* record, size_t field, void * src) 
{ 
    memcpy(record[field].data, src, datatypes[record[field].typetag].size); 
} 

int32_t x = 5; 
set(myrecord, 0, &x); 

для хранения значения в записи, и аналогичный прибудет(), чтобы взять вещи.

Маркированный тип my_var позволяет проверять тип, когда данные находятся внутри my_var, но если в схеме указано, что запись содержит три INT32, нет ничего, что бы проверить, что src указывает на int32_t, а не на мишу, когда вы пытаетесь set() в этот my_var.

Очевидно, что проверка должна выполняться во что-то обертывающем множестве(), прежде чем int32_t * или mystruct * преобразуется в void *. Я видел проверку времени компиляции с помощью трюка typeof(). Я чувствую, что то, чего я хочу, вероятно, невозможно, но вы никогда не знаете всех трюков ...

Есть ли что-нибудь, что я могу сделать лучше, чем предоставлять средства, которые читают схему во время компиляции клиентской программы и генерировать set_CHECKED () макрос оболочки, который даст ошибку компилятора, если кто-то попытается скопировать int32_t в my_var с меткой, чтобы держать минют? Расширения GCC прекрасны.

ответ

0

На самом деле, «набор» и «получить» кажутся правильными местами, чтобы поместить ваши чеки. Если доступ поля с неправильным типом является фатальной ошибки, исправление проста:

void set(my_var* record, size_t field, void * src) 
{ 
    if (record[field].typetag != (my_var)src->typetag) { 
     fprintf(stderr, "Type mismatch!\n"); 
     exit(1); 
    } 
    memcpy(record[field].data, src, datatypes[record[field].typetag].size); 
} 

Если несоответствие типов не является фатальной ошибкой, вам необходимо сделать множество и получить отдачу и код ошибки и обрабатывать это правильно на сайте вызова.

Обратите внимание, что в C, информация о тире информации не указана ко времени создания кода . Поле «typetag» - это единственный способ узнать тип поля .

Конечно, если вам не нужно менять схему без , перекомпилируйте библиотеку, вы можете попробовать создать код C из нее. Это позволит вам использовать проверку типа компилятора во время компиляции.

(также: не имеет большого значения, но my_var.data должна быть пустота *, а не символ * Это не меняет правильность кода, но пустота * говорит читатель (и отладчик), что. тип неизвестен.)

+0

Я отредактирую, чтобы быть более понятным, но аргумент src является указателем на простой тип данных, который нужно сохранить. 'int32_t x = 5;' 'set (myrecord, 0, &x);' Невозможно взять 'src-> typetag'. –

Смежные вопросы