Передача const char * в foo (char *)

0

Пройдя через некоторый код c++ в рамках обзора сертификации PCI DSS, я столкнулся со следующим:

У меня есть метод в некоторой библиотеке, которую мы используем, и одним из ее параметров является char *, скажем, это

void foo(char* arg);

Точка в коде, где он вызывает этот метод, выглядит так:

char mystring[256];
strcpy(mystring, "some value");
....
foo(mystring);

в рамках обзора мы избавляемся от любых strcpy-вызовов (хотя в этом примере это немного тривиально, поскольку "некоторая ценность" явно вписывается в мистификацию)

Таким образом, мы получаем:

char mystring[256];
strncpy(mystring, "some value", sizeof(mystring));
mystring[sizeof(mystring)-1] = '\0';
....
foo(mystring);

Это потому, что я думал

foo("some value")

будет передавать const char *

Однако, к моему удивлению, компилятор (gcc 4) вполне доволен этим. Он даже не дает никаких предупреждений, когда я добавляю -Wall или -Wcast-qual

Мой вопрос заключается в следующем: могу ли я в этом случае безопасно вызвать foo ("некоторое значение"), когда я не знаю, что foo фактически делает (если есть) для его аргумента?

Теги:

3 ответа

10
Лучший ответ

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

  • 5
    Это преобразование не существует с C ++ 11. Строковые литералы не конвертируются в char* .
  • 1
    @ Просто хорошо !!!
8

Могу ли я в этом случае безопасно вызывать foo("some value") когда я не знаю, что foo фактически делает (если что-либо) своим аргументом?

Нет. Строковый литерал является постоянным, и попытка его изменения дает неопределенное поведение.

По историческим причинам существует устаревшее преобразование в non-const char* которое разрешено некоторыми компиляторами, хотя это преобразование больше не действует с С++ 11. Вы не должны полагаться на это, и, надеюсь, вы можете повысить уровень предупреждения на своем компиляторе, чтобы предотвратить его.

Однако, к моему удивлению, компилятор (gcc 4) вполне доволен этим.

Это удивительно. Мой GCC 4.6.3 дает предупреждение по умолчанию; Мне нужно было бы указать -Wno-write-strings чтобы заставить его замолчать.

  • 4
    Конверсия устарела, она не действует в текущем стандарте C ++.
  • 0
    @JonathanWakely: Спасибо, я этого не знал.
2

Кстати, вы используете strncpy неправильно. Параметр размера должен быть размером целевого буфера минус единица:

char mystring[256];
strncpy(mystring, "some value", 255);
mystring[255] = '\0';

Цель состоит в том, чтобы избежать переполнения буфера.

  • 1
    Я заметил, и это была моя ошибка, когда я попытался переписать мою проблему в небольшой пример. Мы используем sizeof (dest), конечно. Спасибо
  • 2
    @Lieuwe Нет, вам нужен sizeof(dest)-1 . Также в C gcc (или, по крайней мере, его ранние версии) не будет рассматривать строковые литералы const если вы не -Wwrite-strings ему -Wwrite-strings предупреждения -Wwrite-strings . Нет, он не включен в -Wall -Wextra , вы должны указать его в дополнение к ним. Это предупреждение необходимо считать обязательным на всех платформах, которые размещают строковые литералы на страницах только для чтения (то есть на всех современных).
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню