GCC: программа не работает с параметром компиляции-O3

Это простой пример учебника, чтобы узнать, как это сделать: XSD How To?



       
              
                     
                            
                                   
                                          
                                                 
                                                        
                                                               
                                                                      
                                                                      
                                                                      
                                                                      
                                                                  
                                                               
                                                           
                                                    
                                             
                                          
                                      
                               
                        
                     
                     
                 
          
   

9
задан Matt J 2 April 2009 в 00:46
поделиться

16 ответов

Теперь, когда Вы отправили фрагмент кода, и рабочее обходное решение было найдено (@Windows ответ программиста), я могу сказать, что, возможно, то, что Вы ищете, -ffloat-store.

- ffloat-хранилище

Не храните переменные с плавающей точкой в регистрах и подавляйте другие опции, которые могли бы измениться, взято ли значение с плавающей точкой от регистра или памяти.

Эта опция предотвращает нежелательную избыточную точность на машинах, таких как 68000, где плавающие регистры (68881) сохраняют больше точности, чем двойное, как предполагается, имеет. Так же для x86 архитектуры. Для большинства программ избыточная точность делает только хороший, но несколько программ полагаются на точное определение плавающей точки IEEE. Используйте - ffloat-хранят для таких программ, после изменения их для хранения всех подходящих промежуточных вычислений в переменные.

Источник: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html

8
ответ дан 4 December 2019 в 06:08
поделиться

отправьте код в расстоянии! это, вероятно, делает некоторое волшебство указателя, видит мое предыдущее сообщение. делание уроки просто скрывает ошибку в Вашем коде путем изменения выделения регистра. еще больше сообщения об этом является выходными вещами изменения!

0
ответ дан 4 December 2019 в 06:08
поделиться

Поскольку обновленный вопрос покажет ;), проблема существует с a std::vector<T*>. Одна распространенная ошибка с векторами является резервом () луг, что должно было быть, изменяют размер () d. В результате Вы записали бы внешние границы массива. Оптимизатор может отбросить те записи.

0
ответ дан 4 December 2019 в 06:08
поделиться

как другой указали, вероятно, строгое искажение. поверните его в o3 и попробуйте еще раз. Мое предположение - то, что Вы делаете некоторые приемы указателя в своем функторе (быстро плавание, поскольку интервал выдерживает сравнение? тип объекта в более низких 2 битах?), что сбой через встраивание шаблонных функций. предупреждения не помогают поймать этот случай. "если компилятор мог бы обнаружить все строгие проблемы искажения, он мог бы точно также избежать их" просто изменение несвязанной строки кода, может заставить проблему появиться или уйти, поскольку он изменяет выделение регистра.

0
ответ дан 4 December 2019 в 06:08
поделиться

Хорошо... Это - одна из самых странных проблем, которые я когда-либо имел.
Я не думаю, что у меня есть достаточно доказательства, чтобы указать, что это - ошибка 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 ;
    }
} ;

К сожалению, эту проблему трудно воспроизвести, потому что это происходит с некоторыми определенными значениями. Я получаю отказ сегментации после сортировки всего один больше чем из тысячи векторов, таким образом, это действительно зависит от определенной комбинации значений, каждый вектор имеет.

1
ответ дан 4 December 2019 в 06:08
поделиться

Ничего себе, я не ожидал ответы так quicly, и так многие...

Ошибка происходит после сортировки станд.:: вектор указателей с помощью станд.:: вид ()

Я обеспечиваю функтор строгого слабого упорядочивания.

Но я знаю функтор, который я обеспечиваю, корректно, потому что я использовал его много, и он хорошо работает.

Плюс, ошибка не может быть некоторым недопустимым указателем в векторе becasue, ошибка происходит как раз в то самое время, когда я сортирую вектор. Если я выполняю итерации через вектор, не применяя станд.:: вид сначала, программа хорошо работает.

Я просто использовал GDB, чтобы попытаться узнать то, что продолжается. Ошибка происходит когда станд.:: вид вызывает мой функтор. Станд. Aparently:: вид передает недопустимый указатель моему функтору. (конечно, это происходит с оптимизированной версией только, любым уровнем оптимизации-O,-O2,-O3),

0
ответ дан 4 December 2019 в 06:08
поделиться

Я ожидаю получать некоторый downvotes здесь после чтения некоторых комментариев, но в консольном игровом мире программирования, это - довольно общепринятая истина, что более высокие уровни оптимизации могут иногда генерировать неправильный код в странных пограничных случаях. Могло бы очень хорошо случиться так, что пограничные случаи могут быть зафиксированы с тонкими изменениями в коде, все же.

1
ответ дан 4 December 2019 в 06:08
поделиться

Столкнулся с той же проблемой несколько дней назад, в моем случае она искажала. И GCC делает это по-другому, но не неправильно, по сравнению с другими компиляторами. GCC стал тем, что некоторые могли бы вызвать адвокатом правил стандарта C++, и их реализация корректна, но также необходимо быть действительно корректными в Вас C++, или это будет оптимизировать somethings, которые являются болью. Но Вы получаете скорость, не, жалуются - также.

2
ответ дан 4 December 2019 в 06:08
поделиться

Это - очень редко отказ компилятора, но компилятор действительно имеет ошибки в них, и их часто проявляются на различных уровнях оптимизации (если существует ошибка в оптимизационном проходе, например).

В целом при создании отчетов о проблемах программирования: предоставьте минимальный пример кода для демонстрации проблемы, такой, что люди могут просто сохранить код в файл, скомпилируйте и выполните его. Сделайте максимально легким воспроизвести Вашу проблему.

Кроме того, попробуйте различные версии GCC (компилирующий Ваш собственный GCC, очень легко, особенно на Linux). Если возможно, попробуйте другим компилятором. Intel C имеет компилятор, который является более или менее совместимым GCC (и свободный для некоммерческого использования, я думаю). Это поможет точному определению проблемы.

3
ответ дан 4 December 2019 в 06:08
поделиться

Можно сталкиваться с проблемой искажения (или это мог быть миллион других вещей). Ищите - fstrict-искажение опции.

На этот вид вопроса невозможно ответить правильно без большей информации.

4
ответ дан 4 December 2019 в 06:08
поделиться

Ошибка находится в Вашем коде. Вероятно, что Вы делаете что-то, что вызывает неопределенное поведение согласно стандарту C, который просто, оказывается, работает без оптимизации, но когда GCC делает определенные предположения для выполнения его оптимизации, повреждения кода, когда те предположения не верны. Удостоверьтесь, что скомпилировали с -Wall опция, и -Wextra мог бы также быть хорошая идея и видеть, получаете ли Вы какие-либо предупреждения. Вы могли также попробовать -ansi или -pedantic, но они, вероятно, приведут к ложным положительным сторонам.

5
ответ дан 4 December 2019 в 06:08
поделиться

Как эксперимент, попытайтесь видеть, будет ли это вызывать компилятор к раунду все последовательно.

volatile float d1=distance(point,p1) ;
volatile float d2=distance(point,p2) ;
return d1 < d2 ;
5
ответ дан 4 December 2019 в 06:08
поделиться

Вот некоторый код, который, кажется, работает, пока Вы не поражаете-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 мы можем быть довольно уверены, что добавление одного к указателю довольно безопасно и просто берет нас к следующей ячейке памяти. В коде выше, происходит проблема, когда мы делаем предположения о том, что содержит та память, который, конечно, стандарт не идет рядом.

7
ответ дан 4 December 2019 в 06:08
поделиться

Я предположил бы, что Ваш код является неправильно первым.
Хотя трудно сказать.

Ваш код компилирует с 0 предупреждениями?

 g++ -Wall -Wextra -pedantic -ansi
7
ответ дан 4 December 2019 в 06:08
поделиться

Это почти (почти) никогда не компилятор.

Во-первых, удостоверьтесь, что Вы компилируете без предупреждений, с - Стена.

Если это не дало Вам "эврика" момент, присоединяет отладчик к наименее оптимизированной версии Вашего исполняемого файла, который отказывает, и посмотрите то, что это делает и куда это идет.

5 получит Вас 10, что Вы решили проблему этой точкой.

2
ответ дан 4 December 2019 в 06:08
поделиться

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).

0
ответ дан 4 December 2019 в 06:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: