Я оптимизирую некоторый код, и у меня есть такая функция:
const char * gStrPtr = NULL;
void foo (const char *str) {
gStrPtr = strdup(str);
}
На данный момент foo()
вызывается только с константными строками. например:
const char fooStr[]="Some really long string...";
foo(fooStr);
Обратите внимание, что, поскольку он всегда вызывается с константой, я могу просто сделать:
void foo (const char *str) {
gStrPtr=str;
}
Но это открывает острую палку: если кто-то в будущем нарушит соглашение и попытается вызвать foo()
с динамической копией строки, которая позже освобождается, это может вызвать неопределенное поведение.
Мне интересно, возможно ли создать во время компиляции или даже во время выполнения проверку, которая проверяет, находится ли str
в памяти только для чтения, чтобы избежать дорогостоящих ошибок в будущем.
Примечание: если я предполагаю, что str является строковым литералом, то я могу сделать это с помощью макроса следующим образом:
#define foo(str) foo_func("" str)
, что приведет к ошибкам компиляции не-строковых литералов. Но он также не принимает указатели на константные символы.
EDIT
Я думал, что выложу это после обсуждения ниже. @CraigEtsy указал на использование __builtin_constant_p
, который является наилучшим способом решения этой проблемы (но, вероятно, будет достаточным для моих нужд). Я сделал следующие тесты с этим, и получил эти результаты:
void foo(const char *str) {
if (__builtin_constant_p(*str))
printf("%s is constant\n", str);
else
printf("%s is not constant\n", str);
}
const char globalArray[] = "globalArray";
const char *globalPtr = "globalPtr";
int main()
{
const char localArray[]="localArray";
const char *localPtr="localPtr";
char localNonConst[]="localNonConst";
foo("literal"); // constant
foo(localArray); // not constant
foo(localPtr); // constant
foo(globalArray); // constant
foo(globalPtr); // not constant
foo(localNonConst); // not constant
}
И при компиляции с -O3 он дал результаты:
literal is constant
localArray is not constant
localPtr is constant
globalArray is constant
globalPtr is not constant
localNonConst is not constant
Итак, для моего конкретного случая я могу просто переключить const char arr[]="str"
на const char * arr="str"
, а затем, в своем foo()
, я могу проверить, является ли значение постоянным, а также выделить память и увеличить время выполнения. предупреждение, если нет (и пометьте флаг, чтобы я знал, нужно ли освобождать указатель позже ...).