ошибка на RELEASE, но не на DEBUG - PullRequest
1 голос
/ 25 июля 2011
std::string s("foo");
sprintf(buf,"%s",s);

Почему, по крайней мере, в MSVC 2010 эта строка кода не содержит ошибок в DEBUG, а содержит ошибки в RELEASE?

Ответы [ 5 ]

9 голосов
/ 25 июля 2011

Спецификатор формата %s ожидает завершения NULL char*. Вы передаете экземпляр std::string. Если это работает в DEBUG, это просто удача.

Вы должны использовать:

std::string s("foo");
sprintf(buf, "%s", s.c_str());

Это извлечет char* и гарантирует, что буфер NULL завершен.

Возможно, что в библиотеке времени выполнения std::string есть разные реализации для DEBUG и RELEASE. Попробуйте скомпилировать, используя оба параметра, но добавив символы отладки в сборку RELEASE, а затем пошагово пройдя код. Посмотрите на область памяти, где хранится s. Есть ли разница?

4 голосов
/ 25 июля 2011

Функции типа Variadic, такие как sprintf(), не являются строго безопасными для типов, так как любой тип аргумента принимается (во время компиляции) как часть набора аргументов с переменными параметрами.

Как показали другие ответы, "%s" - это спецификатор формата, который ожидает завершенную NULL символьную строку. Передача std :: string в этом случае, вероятно, не определена.

Если он работает в режиме отладки, то, скорее всего, просто «повезло», поскольку реализация выдает правильный результат (вероятно, вытекающий из преобразования в стиле c объекта std :: string в символьный указатель).

3 голосов
/ 25 июля 2011

Это не должно работать. Вполне вероятно, что вы попали в неопределенное поведение.

std::string s("foo");
sprintf(buf,"%s",s.c_str());

Вы, вероятно, должны вместо этого использовать потоки.

2 голосов
/ 25 июля 2011

Это неправильно. Вы должны написать это:

std::string s("foo");
sprintf(buf,"%s",s.c_str());

Объект типа std::string не может быть передан в sprintf, так как нет никакого спецификатора формата, соответствующего std::string. Кроме того, %s ожидает объект типа char* или char[], а функция c_str() возвращает char*, поэтому вышеприведенное будет работать.

0 голосов
/ 25 июля 2011

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

struct console_out
{
  static void 
  print(const string& s)
  {
    sprintf(buf, "%s", s.c_str());
  }
  //other overloads should you want them
}

Будьте осторожны один раз, и пусть компилятор будет осторожен после этого.

Иногда я думаю, что такие ошибки слишком просты в c и c ++, но мы можем запутаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...