LINUX.ORG.RU

Ошибка icc или во мне ошибка?

 ,


0

1

Задача: считать из файла дату в формате dd.mm.yyyy и разобрать её по частям. Есть такой код:

#include <stdio.h>

int dd, dm, dy, i;
char s[32], d[5];
FILE *file;

int main() {

  file = fopen("d.txt", "r");

  for(i=0; i<5; i++) {

    fgets(s, 30, file);

    d[0]=s[0];
    d[1]=s[1];
    d[2]=0;
    dd=atoi(d);

    d[0]=s[3];
    d[1]=s[4];
    d[2]=0;
    dm=atoi(d);

    d[0]=s[6];
    d[1]=s[7];
    d[2]=s[8];
    d[3]=s[9];
    d[4]=0;
    dy=atoi(d);

    printf("%i %i %i %s", dd, dm, dy, s);

  }

  fclose(file);

}
Если компилировать его с опцией O1, то всё ОК:
1 9 1995 01.09.1995
4 9 1995 04.09.1995
5 9 1995 05.09.1995
6 9 1995 06.09.1995
7 9 1995 07.09.1995
А если поставить O2 или O3, то фигня:
0 9 1995 01.09.1995
995 9 1995 04.09.1995
995 9 1995 05.09.1995
995 9 1995 06.09.1995
995 9 1995 07.09.1995
Скажите, это я нубло или Интел тупит??


Ответ на: комментарий от post-factum

Компилятор запросто может захотеть это выоптимизировать.

Если он это выоптимизирует с изменением семантики, это баг компилятора.

Пост-фактум, ты поглупел что ли?

Deleted
()
Ответ на: комментарий от p228

Посмотри, какие опции оптимизации включены в -O2 и -O3 в icc.

post-factum ★★★★★
()
Ответ на: комментарий от post-factum

Если в -O2 у icc входит unroll циклов, то это не баг, а фича.

И? После анрола этого цикла семантика программы не меняется.

Deleted
()
Ответ на: комментарий от post-factum

Как это никто?

for(i=0; i<5; i++) {

Я имел в виду, что different accesses (как в вашей ссылке) к переменной i нет.

p228
() автор топика
Ответ на: комментарий от post-factum

Читай ссылку выше.

Ну офигеть теперь, меня послали википедию почитать. :D То есть аргументировать тебе нечем. Ясно.

Deleted
()
Ответ на: комментарий от p228

Выглядит как баг. Семантика должна сохраняться, если нет UB.

Лично я не вижу в коде UB, чтобы компилятор мог с ним такое сотворить в ходе оптимизации. Если PF видит, пусть прямо скажет, а не выпендривается. :D

Deleted
()

Мда.. периодически возникали мысли потыкать icc. Теперь точно трогать эту гадость не буду.

Waterlaz ★★★★★
()
Ответ на: комментарий от p228

Понятия не имею. Больше похоже на баг, т.к. в clang/gcc не воспроизводится. А, может, у Интела свои представления об оптимизации.

post-factum ★★★★★
()
Ответ на: комментарий от Sorcerer

Free C++ Tools. If you are a current student and not paid/compensated for software development, the products below are currently freely available under the non-commercial license for your use. Please select a product to initiate the download process: •Intel® Parallel Studio XE 2015 Professional Edition for C++ Linux*

https://software.intel.com/en-us/intel-education-offerings

Т.е. надо студентом быть.

p228
() автор топика

Бери сгенерированный код и смотри в него до просветления. Оптимизация почти всегда выявляет баги программы, и, сильно реже — баги компилятора.

А всё, чем местные игзперды тебе смогут помочь — свежим анекдотом про объявление счетчика цикла(!) volatile.

alegz ★★★★★
()
    d[0]=s[0];
    d[1]=s[1];
    d[2]=0;

У меня подозрение, что тут компилятор может попытаться записать по адресу d+2 целый многобайтовый 0 с каким-нибудь выравниванием по границе слова. Попробуй '\0' использовать — да, по стандарту тот же int, но у компилятора может быть к символьным литералам отношение другое, чем к целым константам.

alegz ★★★★★
()
Ответ на: комментарий от alegz

А всё, чем местные игзперды тебе смогут помочь — свежим анекдотом про объявление счетчика цикла(!) volatile.

У меня подозрение, что тут компилятор может попытаться записать по адресу d+2 целый многобайтовый 0 с каким-нибудь выравниванием по границе слова.

А ты типа решил свежий анекдот рассказать?

Deleted
()

Исходник выглядит нормально.

(icc нету, но) предлагаю посмотреть на:

  • что пишет icc со включенными предупреждениями: -O2 -Wall -W -Wextra, какие еще есть (icc --help=warnings).
  • не подсказывает ли valgring: собрать прогу с -g -O2 и запустить valgrind ./прога
  • вывалить сюда ассемблерный дамп, в который собирается исходник: собрать с -O2 -g -c -o main.o и показать сюда вывод objdump -r -d -S
sf ★★★
()
Ответ на: комментарий от Deleted

Вот это видишь, родной?

0 9 1995 01.09.1995

Первый ноль как ещё мог появиться, кроме как из-за попадания '\0' в позицию d[1]? При этом в d[2] пытались записать целый 0. Один плюс один сам сложишь?

Хотя, как я уже сказал, без рассмотрения сгенерированного кода это гадание на кофейной гуще.

alegz ★★★★★
()
Ответ на: комментарий от Waterlaz

Они ещё нечто подобное:

if (cpuID.contains("AMD") {
    for (double i = 0.0d; i < 100.0d; i+=0.1d) {
        usleep(i);
    }
}

В бинари вставляют.

EXL ★★★★★
()
Ответ на: комментарий от anonymous

Похоже на icc баг. В OSX тож самое. Отпиши если не сложно тут.

Что отписать-то?

p228
() автор топика
Ответ на: комментарий от p228

Похоже на UB при strict aliasing. Причём это UB внутри atoi. Компилятор не видит связи между входным и выходным параметрами и имеет право переставить вызов atoi туда, куда ему удобно. И сдвигает вызов сразу после первого d[0]=s[0];

monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.