#c #xcode #compiler-errors #c-strings
#c #xcode #ошибки компилятора #c-строки
Вопрос:
Редактировать: Ошибка, похоже, работает. Например, если errno = ERANGE, выводится «Результат слишком большой».
Проблема остается в том, что значение errno не изменяется с 0.
В Xcode я пробовал cerrno
и strerror
с приведенным ниже коротким кодом. Xcode возвращает
sqrt(-1) = nan
Неопределенная ошибка: 0
вместо
sqrt(-1) = -nan
Числовой аргумент вне домена,
как это происходит, например, cpp.sh.
Почему это происходит?
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cerrno>
#include <cstring>
using namespace std;
int main() {
errno = 0;
cout << "sqrt(-1) = " << sqrt(-1) << endl;
cout << strerror(errno) << endl << endl;
return(0);
}
Комментарии:
1. Прежде всего, чтобы удовлетворить мое любопытство (но может быть полезно), не могли бы вы показать нам значение вашего компилятора для
math_errhandling
макроса; например, добавьте эту строку:cout << "math_errhandling = " << math_errhandling << endl;
?2. Привет, он добавляет «math_errhandling = 2».
3. Тогда это все объясняет.
4. Что ж, в этом и заключается проблема! Для установки
errno
этот макрос должен включать1
. (Должно быть 3, чтобы соответствовать C 11, IIRC). Но как это исправить… не знаю.5. Можете ли вы просмотреть свои подробные настройки и / или параметры командной строки компилятора, чтобы узнать, установлен ли где-либо этот
-fno-math-errno
параметр; или просмотрите свой заголовок <cmath> для определения__NO_MATH_ERRNO__
. В качестве альтернативы попробуйте добавить#undef __NO_MATH_ERRNO__
перед вашими#include...
строками.
Ответ №1:
Всякий раз, когда вы хотите проверить errno
после операции, вы всегда должны проверять ее и, возможно, сохранять сразу после операции, которая ее устанавливает. Если вы выполняете другие вызовы функций в промежутках между этой проверкой, даже что-то такое простое, как печать на терминале, вы можете сбиваться errno
.
Одна из возможных причин, по которой это errno
становится 0
возможным, связана с тем фактом, что это обернуто в выражения stream, и нет гарантии, что iostream не устанавливает косвенно (или не отменяет настройку) errno
посредством его реализации.
Если вы когда-нибудь захотите проверить или распечатать errno
причину, вам всегда захочется сохранить результат перед его печатью. Например:
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cerrno>
#include <cstring>
int main() {
errno = 0;
// store errno immediately after the computation
const auto result = std::sqrt(-1);
const auto err = errno;
// then print
std::cout << "sqrt(-1) = " << result << std::endl;
std::cout << std::strerror(err) << std::endl << std::endl;
return 0;
}
Редактировать: Судя по обсуждениям в комментариях OP, это, по-видимому, не является причиной того, что errno
не установлено, а скорее из-за того, что math_errhandling
установлено значение 2
. Я сохраняю этот ответ здесь по архивным причинам, поскольку код в исходном сообщении мог бы так же легко видеть этот результат по причинам, описанным здесь.
Комментарии:
1. Мой плохой; вскоре после публикации этого я увидел обсуждение о
math_errhandling
ответственности. Это неправильный ответ для вашей конкретной проблемы, но я все равно оставлю этот ответ в силе, поскольку это другой возможный источник почемуerrno
может быть не таким, каким вы ожидаете (на случай, если кто-нибудь еще наткнется на этот вопрос)