Ошибка SIGSEGV

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Skwoogey
Сообщения: 63
Зарегистрирован: 11 янв 2016, 02:25

06 окт 2016, 20:33

Писал программу с классами. методы описывал вне классов с помощью пространства имен (в основном). Когда запустил, все тут же упало. С помощью дебаггера определил, что программа падает когда изменяется поле класса, у которого методы описаны снаружи.Возвращает ошибку SIGSEGV. В интернете узнал, что это код ошибки при неправильном обращении к памяти или что-то вроде этого. А в чем секрет краша я так и не понял, ведь методы вне классов можно описывать (по крайней мере нам так рассказывали).

вызов метода 448 строка

Код: Выделить всё

OurCar->MoveCar(&MainMap);
декларация класса строка 31

Код: Выделить всё

class Car
{
    float dir;
    float speed;
    float lth_half;
    float wth_half;
    float x;
    float y;
    float angle;
    float dist;
public:
    Car(float nx, float ny,float nwth, float nlth)
    {
        x = nx;
        y = ny;
        dir = 0.0;
        speed = 0.0;
        lth_half = nlth;
        wth_half = nwth;
        dist = sqrt(lth_half*lth_half +wth_half*wth_half);
        angle = atan(wth_half/lth_half);
    }
    void MoveCar(Map *map);


    void DrawCar();


    float getX();


    float getY();

    float getDIR();

    float getDIST();

    float getANGLE();

    float getWTH();

    float getLTH();

};
описание метода MoveCar строка 183

Код: Выделить всё

void Car::MoveCar(Map *map)
{
    float d_dir = 0.0;
    if(GetAsyncKeyState(VK_UP))
        speed = 0.01;
    else if(GetAsyncKeyState(VK_DOWN))
        speed = -0.01;
    else
        speed = 0.0;

    if(GetAsyncKeyState(VK_LEFT) && speed)
        d_dir = 1.0;
    if(GetAsyncKeyState(VK_RIGHT) && speed)
        d_dir = -1.0;
    dir += d_dir;
    x += cos(dir*PI/180.0)*speed;
    y += sin(dir*PI/180.0)*speed;
    if(map->CollisionCheck(this))
    {
        x -= cos(dir*PI/180.0)*speed;
        y -= sin(dir*PI/180.0)*speed;
        dir -= d_dir;
        speed = 0.0;
    }
}
ну и сам файл, на всякий случай.
[ATTACH]2324[/ATTACH]


Заранее Спасибо за Помощь.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

09 окт 2016, 16:55

В конструкторе Map ты делаешь следующее присваивание:

Код: Выделить всё

Map(char *name, Car *ObjCar)
{
   ...
   ObjCar = new Car(x, y, wth, lth);
   ...
}
Из контекста вызова понятно, что ты думаешь, что проставляешь указатель, переданный снаружи. На самом же деле ты присваиваешь выделенную память не наружному указателю, а копии, созданной на стеке. После завершения конструктора эта копия умрёт, при этом внешний указатель останется неизменным. А так, как он не был инициализирован, то любое обращение к нему даст кору, что ты и наблюдаешь.

Решить проблему можно передав в конструктор не указатель, а ссылку на указатель. Правда, если честно, я бы вообще всё переделал, так как в текущем варианте кода у тебя не определён владелец OurCar. Да и output параметр конструктора Map - это вообще какой-то костыль. Было бы куда логичнее конструировать Car, передав ему ссылку на Map, откуда он сможет взять необходимые параметры.

И вообще, судя по беглому взгляду на код видно, что он прямо пропитан непонимаем того, что человек делает... Скажем, Sleep внутри цикла обработки сообщений. Более детально я даже побоялся смотреть дабы сэкономить собственные нервы :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Skwoogey
Сообщения: 63
Зарегистрирован: 11 янв 2016, 02:25

09 окт 2016, 17:15

Черт, совсем забыл, что он делает копию указателя. Спасибо за помощь.

Я брал заготовку кода опенГЛ (Точнее мне его дал мой ИДЕ) и да, вы правы, что я не понимаю как работает создание окна, а Sleep там был уже и, честно говоря, я не понимаю в чем проблема. Вроде как небольшая задержка между фреймами не помешает. Класс Car задумывался, как свой собственный, и должен удалятся в мейне(Или чем бы оно ни было в библиотеке винды). А если передавать машине ссылку на карту, то в карте нужно создать переменные для хранения начальных координат и размеров машины. И стоит ли оно того? ради разового случая создать 4 переменные и/или указателя. Либо я не понял, что вы имеете ввиду. Не бейте сильно, "ссылки" я только в теории учил, но на практике не применял и слабо понимаю, что они вообще такое.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

09 окт 2016, 17:45

Skwoogey писал(а):Черт, совсем забыл, что он делает копию указателя. Спасибо за помощь.
Не за что. Для этого тут и посиживаю :)
Skwoogey писал(а): Я брал заготовку кода опенГЛ (Точнее мне его дал мой ИДЕ) и да, вы правы, что я не понимаю как работает создание окна, а Sleep там был уже и, честно говоря, я не понимаю в чем проблема. Вроде как небольшая задержка между фреймами не помешает.
А проблема в том, что на 1 секунду у тебя будет подвисать не только перерисовка карты (что и задумывалось), но ещё и весь цикл обработки сообщений. То есть, скажем ухватил пользователь окно мышкой, передвинул на новое место, а оно подвисло и перерисовалось только спустя секунду. И так будет тормозить любая реакция окна на действия пользователя. Может оно и терпимо, так как задачка тренировочная, но по-хорошему отрисовку нужно, как минимум, вешать на таймер. Так или иначе, Sleep - это зло.
Skwoogey писал(а): Класс Car задумывался, как свой собственный, и должен удалятся в мейне(Или чем бы оно ни было в библиотеке винды).
Задумывался, но не удаляется. Вызова delete я не нашёл :)
Skwoogey писал(а): А если передавать машине ссылку на карту, то в карте нужно создать переменные для хранения начальных координат и размеров машины. И стоит ли оно того? ради разового случая создать 4 переменные и/или указателя.
Стоит ради правильности архитектуры. В любом случае output параметр конструктора - это неоправданной кривизны костыль. Конструктор должен инициализировать поля класс, а не создавать внешние объекты других классов.

Смотри, а давай вообще с другой стороны зайдём. Ты испытываешь трудности с тем, чтобы пропихнуть в класс Car данные из внешнего файла. Причём файл называется "test map.map", то есть это файл-карта. Задумайся, почему у тебя координаты автомобиля лежат в файле-карте. Логично ли это?

Если ты всё же убеждён, что автомобиль нужно считать частью карты, то тогда делай его частью карты и в коде (скажем, вводи в классе Map необходимые поля, и храни инфу об автомобиле в них, либо если хочешь отдельный класс, то аггрегируй этот класс в Map). Тогда не понадобится передавать в конструтор Map внешний указатель на Car.

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

И в первом и во втором случае ты избавишься от output параметра, от которого нужно избавляться в любом случае.
Skwoogey писал(а):Не бейте сильно, "ссылки" я только в теории учил, но на практике не применял и слабо понимаю, что они вообще такое.
С ссылками обязательно разберись. Без их понимания серьёзных программ не получится написать.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Skwoogey
Сообщения: 63
Зарегистрирован: 11 янв 2016, 02:25

09 окт 2016, 18:15

Romeo писал(а): А проблема в том, что на 1 секунду у тебя будет подвисать не только перерисовка карты (что и задумывалось), но ещё и весь цикл обработки сообщений. То есть, скажем ухватил пользователь окно мышкой, передвинул на новое место, а оно подвисло и перерисовалось только спустя секунду. И так будет тормозить любая реакция окна на действия пользователя. Может оно и терпимо, так как задачка тренировочная, но по-хорошему отрисовку нужно, как минимум, вешать на таймер. Так или иначе, Sleep - это зло.
там ведь вроде в мс считается, а не в секундах.
Romeo писал(а): Задумывался, но не удаляется. Вызова delete я не нашёл :)
Еще будет.
Romeo писал(а): Если ты всё же убеждён, что автомобиль нужно считать частью карты, то тогда делай его частью карты и в коде (скажем, вводи в классе Map необходимые поля, и храни инфу об автомобиле в них, либо если хочешь отдельный класс, то аггрегируй этот класс в Map). Тогда не понадобится передавать в конструтор Map внешний указатель на Car.
Хорошо, А если агрегировать, то можно ли сделать поле машины публичным, чтобы не дописывать кучу функций или это тоже плохой тон (хотя машина у меня закрыта)? Отдельно я их не хочу кидать, так как логика коллизии у меня не предусматривала выталкивание машины из домика, а только работает на не пропускание, а меня такой уровень устраивает. Если их отдельно писать, то вероятность ошибки больше.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

09 окт 2016, 18:39

Если агрегировать, то куча методов не нужна. Достаточно одного метода, который будет возвращать указатель/ссылку на машину. А вот если агрегации не будет, а поля машины будут среди полей карты, то тогда да, на каждое поле нужен будет геттер-метод. Иначе никак. Поля в public секции - это нарушение инкапсуляции.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить