Это простой пример учебника, чтобы узнать, как это сделать: XSD How To?
Теперь, когда Вы отправили фрагмент кода, и рабочее обходное решение было найдено (@Windows ответ программиста), я могу сказать, что, возможно, то, что Вы ищете, -ffloat-store
.
- ffloat-хранилище
Не храните переменные с плавающей точкой в регистрах и подавляйте другие опции, которые могли бы измениться, взято ли значение с плавающей точкой от регистра или памяти.
Эта опция предотвращает нежелательную избыточную точность на машинах, таких как 68000, где плавающие регистры (68881) сохраняют больше точности, чем двойное, как предполагается, имеет. Так же для x86 архитектуры. Для большинства программ избыточная точность делает только хороший, но несколько программ полагаются на точное определение плавающей точки IEEE. Используйте - ffloat-хранят для таких программ, после изменения их для хранения всех подходящих промежуточных вычислений в переменные.
Источник: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html
отправьте код в расстоянии! это, вероятно, делает некоторое волшебство указателя, видит мое предыдущее сообщение. делание уроки просто скрывает ошибку в Вашем коде путем изменения выделения регистра. еще больше сообщения об этом является выходными вещами изменения!
Поскольку обновленный вопрос покажет ;), проблема существует с a std::vector<T*>
. Одна распространенная ошибка с векторами является резервом () луг, что должно было быть, изменяют размер () d. В результате Вы записали бы внешние границы массива. Оптимизатор может отбросить те записи.
как другой указали, вероятно, строгое искажение. поверните его в o3 и попробуйте еще раз. Мое предположение - то, что Вы делаете некоторые приемы указателя в своем функторе (быстро плавание, поскольку интервал выдерживает сравнение? тип объекта в более низких 2 битах?), что сбой через встраивание шаблонных функций. предупреждения не помогают поймать этот случай. "если компилятор мог бы обнаружить все строгие проблемы искажения, он мог бы точно также избежать их" просто изменение несвязанной строки кода, может заставить проблему появиться или уйти, поскольку он изменяет выделение регистра.
Хорошо... Это - одна из самых странных проблем, которые я когда-либо имел.
Я не думаю, что у меня есть достаточно доказательства, чтобы указать, что это - ошибка GCC, но честно... Это действительно похоже на тот.
Это - мой исходный функтор. Тот, который хорошо работает без уровней оптимизации и бросает отказ сегментации с любым уровнем оптимизации:
struct distanceToPointSort{
indexedDocument* point ;
distanceToPointSort(indexedDocument* p): point(p) {}
bool operator() (indexedDocument* p1,indexedDocument* p2){
return distance(point,p1) < distance(point,p2) ;
}
} ;
И эти работы безупречно с любым уровнем оптимизации:
struct distanceToPointSort{
indexedDocument* point ;
distanceToPointSort(indexedDocument* p): point(p) {}
bool operator() (indexedDocument* p1,indexedDocument* p2){
float d1=distance(point,p1) ;
float d2=distance(point,p2) ;
std::cout << "" ; //without this line, I get a segmentation fault anyways
return d1 < d2 ;
}
} ;
К сожалению, эту проблему трудно воспроизвести, потому что это происходит с некоторыми определенными значениями. Я получаю отказ сегментации после сортировки всего один больше чем из тысячи векторов, таким образом, это действительно зависит от определенной комбинации значений, каждый вектор имеет.
Ничего себе, я не ожидал ответы так quicly, и так многие...
Ошибка происходит после сортировки станд.:: вектор указателей с помощью станд.:: вид ()
Я обеспечиваю функтор строгого слабого упорядочивания.
Но я знаю функтор, который я обеспечиваю, корректно, потому что я использовал его много, и он хорошо работает.
Плюс, ошибка не может быть некоторым недопустимым указателем в векторе becasue, ошибка происходит как раз в то самое время, когда я сортирую вектор. Если я выполняю итерации через вектор, не применяя станд.:: вид сначала, программа хорошо работает.
Я просто использовал GDB, чтобы попытаться узнать то, что продолжается. Ошибка происходит когда станд.:: вид вызывает мой функтор. Станд. Aparently:: вид передает недопустимый указатель моему функтору. (конечно, это происходит с оптимизированной версией только, любым уровнем оптимизации-O,-O2,-O3),
Я ожидаю получать некоторый downvotes здесь после чтения некоторых комментариев, но в консольном игровом мире программирования, это - довольно общепринятая истина, что более высокие уровни оптимизации могут иногда генерировать неправильный код в странных пограничных случаях. Могло бы очень хорошо случиться так, что пограничные случаи могут быть зафиксированы с тонкими изменениями в коде, все же.
Столкнулся с той же проблемой несколько дней назад, в моем случае она искажала. И GCC делает это по-другому, но не неправильно, по сравнению с другими компиляторами. GCC стал тем, что некоторые могли бы вызвать адвокатом правил стандарта C++, и их реализация корректна, но также необходимо быть действительно корректными в Вас C++, или это будет оптимизировать somethings, которые являются болью. Но Вы получаете скорость, не, жалуются - также.
Это - очень редко отказ компилятора, но компилятор действительно имеет ошибки в них, и их часто проявляются на различных уровнях оптимизации (если существует ошибка в оптимизационном проходе, например).
В целом при создании отчетов о проблемах программирования: предоставьте минимальный пример кода для демонстрации проблемы, такой, что люди могут просто сохранить код в файл, скомпилируйте и выполните его. Сделайте максимально легким воспроизвести Вашу проблему.
Кроме того, попробуйте различные версии GCC (компилирующий Ваш собственный GCC, очень легко, особенно на Linux). Если возможно, попробуйте другим компилятором. Intel C имеет компилятор, который является более или менее совместимым GCC (и свободный для некоммерческого использования, я думаю). Это поможет точному определению проблемы.
Можно сталкиваться с проблемой искажения (или это мог быть миллион других вещей). Ищите - fstrict-искажение опции.
На этот вид вопроса невозможно ответить правильно без большей информации.
Ошибка находится в Вашем коде. Вероятно, что Вы делаете что-то, что вызывает неопределенное поведение согласно стандарту C, который просто, оказывается, работает без оптимизации, но когда GCC делает определенные предположения для выполнения его оптимизации, повреждения кода, когда те предположения не верны. Удостоверьтесь, что скомпилировали с -Wall
опция, и -Wextra
мог бы также быть хорошая идея и видеть, получаете ли Вы какие-либо предупреждения. Вы могли также попробовать -ansi
или -pedantic
, но они, вероятно, приведут к ложным положительным сторонам.
Как эксперимент, попытайтесь видеть, будет ли это вызывать компилятор к раунду все последовательно.
volatile float d1=distance(point,p1) ;
volatile float d2=distance(point,p2) ;
return d1 < d2 ;
Вот некоторый код, который, кажется, работает, пока Вы не поражаете-O3...
#include <stdio.h>
int main()
{
int i = 0, j = 1, k = 2;
printf("%d %d %d\n", *(&j-1), *(&j), *(&j+1));
return 0;
}
Без оптимизаций я добираюсь "2 1 0"; с оптимизациями я добираюсь "40 1 2293680". Почему? Поскольку я и k были оптимизированы!
Но я брал адрес j и выходил из региона памяти, выделенного j. Это не позволяется стандартом. Наиболее вероятно, что Ваша проблема вызывается подобным отклонением от стандарта.
Я нахожу, что valgrind время от времени часто полезен как они.
Править: У некоторых комментаторов создается впечатление, что стандарт позволяет произвольную адресную арифметику с указателями. Это не делает. Помните, что некоторая архитектура имеет забавные схемы адресации, выравнивание может быть важным, и можно получить проблемы при переполнении определенных регистров!
Слова [чернового] стандарта, при добавлении/вычитании целого числа к/от указателю (добавленный акцент):
"Если и операнд указателя и результат укажут на элементы того же объекта массива или одно прошлое последний элемент объекта массива, то оценка не должна производить переполнение; иначе поведение не определено".
Наблюдение как &j даже не указывает на объект массива, &j-1, и &j+1 может едва указать на часть того же объекта массива. Так просто оценивающий &j+1 (уже не говоря о разыменовании его) неопределенное поведение.
На x86 мы можем быть довольно уверены, что добавление одного к указателю довольно безопасно и просто берет нас к следующей ячейке памяти. В коде выше, происходит проблема, когда мы делаем предположения о том, что содержит та память, который, конечно, стандарт не идет рядом.
Я предположил бы, что Ваш код является неправильно первым.
Хотя трудно сказать.
Ваш код компилирует с 0 предупреждениями?
g++ -Wall -Wextra -pedantic -ansi
Это почти (почти) никогда не компилятор.
Во-первых, удостоверьтесь, что Вы компилируете без предупреждений, с - Стена.
Если это не дало Вам "эврика" момент, присоединяет отладчик к наименее оптимизированной версии Вашего исполняемого файла, который отказывает, и посмотрите то, что это делает и куда это идет.
5 получит Вас 10, что Вы решили проблему этой точкой.
The true answer is hidden somewhere inside all the comments in this thread. First of all: it is not a bug in the compiler.
The problem has to do with floating point precision. distanceToPointSort
should be a function that should never return true for both the arguments (a,b) and (b,a), but that is exactly what can happen when the compiler decides to use higher precision for some data paths. The problem is especially likely on, but by no means limited to, x86 without -mfpmath=sse
. If the comparator behaves that way, the sort
function can become confused, and the segmentation fault is not surprising.
I consider -ffloat-store
the best solution here (already suggested by CesarB).