2016-01-29 2 views
8

Я хотел бы написать функцию протоколирования низкого уровня, который будет выглядеть так:тест C, если переменная только для чтения раздел

DO_DBG("some string", val1, val2) 

То, что я хочу, чтобы это сделать, чтобы хранить указатель строка, а не копия строки, по соображениям производительности. Это предполагает, что строка является литералом только для чтения. Чтобы люди не могли отлаживать отладчик, было бы неплохо, если компилятор мог бы пожаловаться, если первый параметр DO_DBG был в разделе для записи кода и текста и т. Д. Мне интересно, существует ли механизм для этого. (Я использую gcc 4.9.1, ld 2.24).

+1

Если произвольная ** переменная ** или ** строка литерала ** доступна только для чтения? Стандарт C гарантирует строковые литералы только для чтения.Однако он определяется реализацией, если одинаковые строки хранятся по одному и тому же адресу. – Downvoter

+0

Да, но я хочу, чтобы компилятор отказался от компиляции, если кто-то пытается передать что-либо, кроме строкового литерала, в качестве первого параметра функции. Функция примет параметр 'const char *', и я хочу знать, является ли это литералом ... – John

+0

Это похоже на обход неопределенного поведения и замену его чем-то «более безопасным», например, ошибки времени компиляции. Я не думаю, что это возможно без изменения компилятора/нарушения стандарта C. – Downvoter

ответ

7

Вы можете использовать автоматическую строковую конкатенацию в свою пользу:

#define DO_DBG(s, a, b) _DO_DBG("" s, a, b) 

И реализовать свой реальный макрос _DO_DBG.

+1

Что делать, если пользователи регистрируют значение '-10'? –

+0

@KerrekSB - тогда будет вызвана требуемая ошибка времени компиляции. – Amit

+0

Он говорил о струнах ... –

0

В качестве альтернативы можно использовать stringify макросъемки конструкцию:

#define DO_DBG(s, a, b) DO_DBG_INTERNAL(# s, a, b) 

и вызвать вашу функцию DO_DGB_INTERNAL так что люди будут делать:

DO_DBG(some string, val1, val2) 

PS, вполне возможно, VARIADIC функция и макрос будет хорошая идея здесь.

+0

Результат строкой снова является константной строкой, которая будет обрабатываться так же, как строка, написанная программистом. Это не должно меняться. – vonbrand

+0

Если вы выполните: 'DO_DBG (some_charstar_var, ...)', вы обязательно избегаете проблемы изменения 'some_charstar_var' изменения, влияющего на то, что хранится в DO_DBG ... –

+0

Нет. Обработка varargs полностью выполняется во время выполнения. – vonbrand

0

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

Кроме вышеуказанного, если ваша программа не зависит от неопределенного поведения (уйти с записью на постоянной строке), вы не сможете определить, есть ли она в постоянной памяти или нет. Вы можете сравнить адреса строк, чтобы увидеть, являются ли они только одной копией, но это все.

В любом случае, если вы не знаете, как это сделать, то вы не увидите (или не более, очень маленькую) разницу в производительности, если строка прочитана - только чтение-запись, одна копия или несколько.

Если вы пишете вы действуете с параметром char *, и магазин сказал указатель в сторону (не копию строки, указанной), вы должны всегда получить ту же строку обратно (если среда не является действительно странно).

1

Вы можете настроить SIGSEGV обработчик, а затем попытаться сделать:

s[0] = s[0]; 

Если обработчик срабатывает, то это означает, что переменная находится в режиме только для чтения сегмента, так что вы можете сохранить указатель , Если нет, вы можете жаловаться (или просто сделать копию строки).

Вам нужно объявить строку volatile, чтобы компилятор не оптимизировал задание.

+0

Это будет работать во время выполнения, но OP ищет проверку времени компиляции. – dbush

+0

Ах, не понимал этого. Он говорил о областях памяти только для чтения и записи, которые выглядят как проблема времени исполнения. – Barmar

+0

Это интересный подход к тестированию только для чтения. Это может быть полезно в чем-то еще в будущем. – John

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