Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.10.2013, 07:36   #1
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,601
По умолчанию Ошибка сегментирования

Есть реализованный класс, который отвечает за рисование круга, окружности.
Хедер:
Код:
class CircleCos2D
{
   public:
    CircleCos2D(double s, double r);
    void Reshape(double s,double r);
    void Paint();
    void Coords(float x, float y);
   private:
    int      count;
    double   r;
    double   xc,yc;
    double * x;
    double * y;
};
Описание
Код:
CircleCos2D::CircleCos2D(double s,double r)
{
    x=new double[1]; // Создаем динамический массив, чтобы небыло ошибки
    y=new double[1]; // сегментирования
    if ((double)r/(double)s<0.6)
    {
      printf("Отношение радиуса к отрезку превышает критический минимум");
    }
    Reshape(s,r);
}

void CircleCos2D::Reshape(double s,double r)
{
    delete[] x;
    delete[] y;
    double angle = acos((r*r+r*r-s*s)/(2*r*r));
    count = ((double)pi*2.0/(double)angle)+1;
    x=new double[count];
    y=new double[count];
    int ct = count/2;
    for (int i=0;i<=ct;i++)
    {
       x[i]=r*cos(angle*i);
       x[i+ct]=-x[i];
       y[i]=r*sin(angle*i);
       y[i+ct]=-y[i];
    }
   
}

void CircleCos2D::Paint()
{
    glBegin(GL_POLYGON);
     for (int i=0;i<=count;i++)
     {
         glVertex2d(x[i]+xc,y[i]+yc);
     }
     glVertex2d(x[0]+xc,y[0]+yc);
    glEnd();
  
}
void CircleCos2D::Coords(float x, float y)
{
    xc=x;
    yc=y; 
}
Я создаю указатель на класс(в моем коде ниже это "cr") и соответственно использую его. При вращении колеса мыши, круг масштабируется.
Код:
if((button==4))
        {
          Env.r*=1.01;
          cr->Reshape(0.01,Env.r);
        }
На cr->Reshape(0.01,Env.r); программа валится, а так как она в полноэкранном режиме, все зависает(Диспетчер задач не может ничего закрыть). Если закомментировать, то никаких ошибок не наблюдается, но и масштаб объекта, главное в приложении, не работает Самое удивительное, что эта программа полностью работоспособна на ОС с ядром Linux. Все это возникло из-за того, что я захотел перенести ее на Windows. Написано с использованием GLUT. Кроссплатформенно компилируется, но на Windows, как я говорил, вылетает.

Еще один факт. В конструкторе класса также вызывается Reshape, но приложение не вылетает. Вызов конструктора происходит в main.

P.S. пользуясь случаем, хотелось бы узнать о существовании русских информационных сайтов или статей о OpenGL 3+.

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог
_PROGRAMM_ вне форума Ответить с цитированием
Старый 08.10.2013, 09:17   #2
Shad0wF1rst
Форумчанин
 
Регистрация: 11.01.2013
Сообщений: 149
По умолчанию

Цитата:
На cr->Reshape(0.01,Env.r); программа валится, а так как она в полноэкранном режиме, все зависает(Диспетчер задач не может ничего закрыть). Если закомментировать, то никаких ошибок не наблюдается, но и масштаб объекта, главное в приложении, не работает Самое удивительное, что эта программа полностью работоспособна на ОС с ядром Linux. Все это возникло из-за того, что я захотел перенести ее на Windows. Написано с использованием GLUT. Кроссплатформенно компилируется, но на Windows, как я говорил, вылетает.
Приведенный код класса это хорошо, но хотелось бы видеть больше кода предшествующего тому месту где у вас валится приложение.

P.S. В конструкторе класса вместо того что бы выделять 1 байт массива динамически, просто приравняй указатели нулю и ошибки сегментирования не будет при удалении нулевого указателя.
Может это и чушь, но это моя чушь и я ее никому не отдам.
Shad0wF1rst вне форума Ответить с цитированием
Старый 08.10.2013, 14:17   #3
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,601
По умолчанию

Цитата:
Приведенный код класса это хорошо, но хотелось бы видеть больше кода предшествующего тому месту где у вас валится приложение.
Как-то так. На Linux ведь работает! Причем отлично.

Код:
void MouseDown(int button,int state,int x, int y)
{
     Xf = XScreen*2*(float)x/(float)width-(XScreen);
     Yf = -(YScreen*2*(float)y/(float)height-(YScreen));

     if (button==GLUT_RIGHT_BUTTON)
     {
        bool select=false;
        for (int i=0;i<=count_object;i++)
        {
           double s = sqrt(pow(Planet[i]->Pos.x-Xf,2)+pow(Planet[i]->Pos.y-Yf,2));
           if (Planet[i]->r > s)
           {
             select_object=i;
             select=true;
           }
        }
        if (select==false)
        select_object = -1;
     }

     if((button==GLUT_LEFT_BUTTON)&&(state==GLUT_DOWN)&&(select_object!=-1))
     {
          Planet[select_object]->Speed.x+=(Xf-Planet[select_object]->Pos.x)/200.0;
          Planet[select_object]->Speed.y+=(Yf-Planet[select_object]->Pos.y)/200.0;

          if (select_object>count_object)
          {
             Planet[select_object]->m       = Env.p*rpi*pow(Env.r,3);
             count_object++;
          }
     }

     if((keys[78]==true)||(keys[110]==true))
     {

        if((button==GLUT_LEFT_BUTTON)&&(state==GLUT_DOWN))
        {
           for(int i=0;i<=count_object;i++)
           {
             printf("Номер %i \n",i);
             printf("Масса    %f\n",Planet[i]->m);                 
             printf("Скорость X:%f.3 Y:%f.3\n",Planet[i]->Speed.x,Planet[i]->Speed.y);      
             printf("Позиция  X:%f.3 Y:%f.3\n\n",Planet[i]->Pos.x,Planet[i]->Pos.y);      
           }
           int s = count_object+1;
           Planet[s]               = new Body(Env.r);
           Planet[s]->Pos.x        = Xf;
           Planet[s]->Pos.y        = Yf;
           select_object=s;
        }
        if((button==4))
        {
          Env.r*=1.01;
          cr->Reshape(0.01,Env.r);
        }
        if((button==3)&&(Env.r>0.1))
        {
          Env.r/=1.01;
          cr->Reshape(0.01,Env.r);
        }
     }
     else
     {
        if(button==4)
          Env.dScale*=1.05;
        if(button==3)
          Env.dScale/=1.05;
        Reshape(width,height);
     }
     
}
Цитата:
P.S. В конструкторе класса вместо того что бы выделять 1 байт массива динамически, просто приравняй указатели нулю и ошибки сегментирования не будет при удалении нулевого указателя.
Будет сделано. Спасибо.

---

Вот еще факт.
Инициализация класса у меня происходит в main вот так.
Код:
cr = new  CircleCos2D(0.01,0.1);
Если добавить строку с пересчетом
Код:
cr = new  CircleCos2D(0.01,0.1);
	cr->Reshape(0.01,Env.r);
, то сразу же вылетает. Замечу, что поставил я их в самое начало main. Скриншот прилагается.
Изображения
Тип файла: jpg Error.jpg (32.0 Кб, 54 просмотров)

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог

Последний раз редактировалось _PROGRAMM_; 08.10.2013 в 15:31.
_PROGRAMM_ вне форума Ответить с цитированием
Старый 08.10.2013, 16:17   #4
Shad0wF1rst
Форумчанин
 
Регистрация: 11.01.2013
Сообщений: 149
По умолчанию

Я так и не нашел чему же все таки равно начальное значение Env.r. Думаю в нем дело. Так как вы в конструкторе вызываете свою функцию:
Код:
CircleCos2D::CircleCos2D(double s,double r)
{
    x=new double[1]; // Создаем динамический массив, чтобы небыло ошибки
    y=new double[1]; // сегментирования
    if ((double)r/(double)s<0.6)
    {
      printf("Отношение радиуса к отрезку превышает критический минимум");
    }
    Reshape(s,r);
}
И оно реагирует нормально когда вы задаете числа, и у вас возникает ошибка только когда вы пытаетесь второй аргумент передать Env.r
Может это и чушь, но это моя чушь и я ее никому не отдам.
Shad0wF1rst вне форума Ответить с цитированием
Старый 08.10.2013, 16:59   #5
Igor95
Форумчанин
 
Регистрация: 03.01.2013
Сообщений: 388
По умолчанию

С чего это Вы взяли, что при использовании динамической памяти не будет ошибки сегментирования?
Код:
void CircleCos2D::Reshape(double s,double r)
{
    delete[] x;
    delete[] y;
    double angle = acos((r*r+r*r-s*s)/(2*r*r));
    count = ((double)pi*2.0/(double)angle)+1;
    x=new double[count];
    y=new double[count];
    int ct = count/2;
    for (int i=0;i<=ct;i++)
    {
       x[i]=r*cos(angle*i);
       x[i+ct]=-x[i];
       y[i]=r*sin(angle*i);
       y[i+ct]=-y[i];
    }
   
}
Вот здесь подозрительно. Проверьте, а не выходите ли Вы за пределы выделенной памяти под массив.
Igor95 вне форума Ответить с цитированием
Старый 08.10.2013, 18:57   #6
_PROGRAMM_
Участник клуба
 
Аватар для _PROGRAMM_
 
Регистрация: 30.07.2009
Сообщений: 1,601
По умолчанию

Проблему решил, смотрите конец сообщения.

Сделал так
Код:
Env.r=Env.r * 1.01;
printf("%f\n",Env.r);
//cr->Reshape(0.01,Env.r);
Ошибки нет. Env.r выводится исправно (см. вложение). Еще когда отписывался, такая мысль возникла. Я провел несколько экспериментов и был уверен, что проблема в Env.r.
Цитата:
С чего это Вы взяли, что при использовании динамической памяти не будет ошибки сегментирования?
1. Потому что в Linux ее нет.
2. Я такого не говорил.
Цитата:
Вот здесь подозрительно. Проверьте, а не выходите ли Вы за пределы выделенной памяти под массив.
Будем смотреть...

А теперь самое интересное. Код в начале
Код:
cr = new  CircleCos2D(0.01,0.1);
cr->Reshape(0.01,Env.r);
вылетал из-за того, что я не инициализировал Env.r. После инициализации он работает. НО!
Не соответствует никакой логике:
Этот код работает:
Код:
cr = new  CircleCos2D(0.01,0.1);
	cr->Reshape(0.01,Env.r);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1);
Этот тоже:
Код:
cr = new  CircleCos2D(0.01,0.1);
	cr->Reshape(0.01,Env.r);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1*1.01);
Этот НЕТ!
Код:
cr->Reshape(0.01,Env.r);
	cr->Reshape(0.01,0.1);
	cr->Reshape(0.01,0.1*1.01);
	cr->Reshape(0.01,0.1*1.01*1.01);
А этот опять работает
Код:
cr = new  CircleCos2D(0.01,0.1);
	cr->Reshape(0.01,Env.r);
	cr->Reshape(0.01,0.1*1.01*1.01);
Такой тоже функционирует
Код:
cr = new  CircleCos2D(0.01,0.1);
	cr->Reshape(0.01,Env.r);
	cr->Reshape(0.01,0.1*1.01*1.01);
	cr->Reshape(0.01,0.1*1.01*1.01);
	cr->Reshape(0.01,0.1*1.01*1.01);
	cr->Reshape(0.01,0.1*1.01*1.01);
Проблема все-таки в классе. Т.к. другие элементы структуры Env исправно работают, храня масштаб сцены и шкалу.

---
Цитата:
Проверьте, а не выходите ли Вы за пределы выделенной памяти под массив.
Вы были правы. На один элемент запрыгнул. Получается g++ сам за меня округлил ct в меньшую сторону, а вот Microsoft, к сожалению, не смог.

Shad0wF1rst и Igor95, огромное спасибо, я вам очень благодарен.
Изображения
Тип файла: jpg printf.jpg (45.6 Кб, 49 просмотров)

В мире нет вечных двигателей, зато есть вечные тормоза...

Блог

Последний раз редактировалось _PROGRAMM_; 08.10.2013 в 19:13.
_PROGRAMM_ вне форума Ответить с цитированием
Старый 08.10.2013, 21:42   #7
Igor95
Форумчанин
 
Регистрация: 03.01.2013
Сообщений: 388
По умолчанию

Пожалуйста
Igor95 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка сегментирования Evgenuych96 Общие вопросы C/C++ 4 17.03.2013 13:51
Ошибка сегментирования при разборе командной строки Демик Помощь студентам 4 30.03.2012 23:01
Не работает код, вылетает ошибка сегментирования Avitella Общие вопросы C/C++ 6 21.12.2011 22:20
Ошибка сегментирования при вызове strcat Кипящий чайник Общие вопросы C/C++ 4 05.03.2011 20:49
Ошибка сегментирования Olechka555 Общие вопросы C/C++ 1 14.09.2010 08:50