Russian Qt Forum

Программирование => С/C++ => Тема начата: akuta от Сентябрь 07, 2015, 17:02



Название: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 17:02
Есть классы:
Код:
class PValue
{
public:
    char type;
    int int_num;
    long long long_num;
    float float_num;
    double double_num;
    QString str;
    int arr_dim;
    int arr_sizes[MAX_DIMEN]; // 510
    PValue()
    {
        type=0;
        int_num=0; long_num=0;
        float_num=0.0f; double_num=0.0d;
        arr_dim=0;
    }
};
И использующий его
Код:
class PVariable
{
public:
    char name[33];
    PValue value;
};
Также есть структура
Код:
struct PFunct
{
    char name[33];
    int addr;
    char ret_type;
    int arg_count;
    char args[STACK_SIZE];   //510
    int local_variables_count;
    PVariable *local_variables; //Вот тут используется класс, указанный выше
    PFunct(){addr=0; local_variables_count=0; local_variables=0;}
};
Это всё грузится из файла и при попытке создать массив local_variables код абсолютно рандомно крашится.
Вот код создания:
Код:
f->local_variables=new PVariable[loc_count];
Переменная f создана, указатель валиден. loc_count равен 4.
Вот результат дебаггера:
(http://puu.sh/k31Fn/aa2b0bd093.PNG)
Я не понимаю, что я делаю не так. Дебаггер не может найти конкретное место падения даже, последняя строка, до которой он доходит по шагам, это вот та строка с new.


Название: Re: Неотлаживаемый код
Отправлено: Tuxford от Сентябрь 07, 2015, 17:16
Сделал вот такую штуку:
Цитировать
#include <string>

#define MAX_DIMEN 510

class PValue
{
public:
    char type;
    int int_num;
    long long long_num;
    float float_num;
    double double_num;
    std::string str;
    int arr_dim;
    int arr_sizes[MAX_DIMEN]; // 510
    PValue()
    {
        type=0;
        int_num=0; long_num=0;
        float_num=0.0f; double_num=0.0f;
        arr_dim=0;
    }
};

#define STACK_SIZE MAX_DIMEN

class PVariable
{
public:
    char name[33];
    PValue value;
};
struct PFunct
{
    char name[33];
    int addr;
    char ret_type;
    int arg_count;
    char args[STACK_SIZE];   //510
    int local_variables_count;
    PVariable *local_variables; //Вот тут используется класс, указанный выше
    PFunct(){addr=0; local_variables_count=0; local_variables=0;}
};

int main(int argc, char** argv)
{
   PFunct *pf = new PFunct();
   pf->local_variables = new PVariable[2];
   return 0;
}
Ничего не закрешилось. Лень было qt подключать.
Скорее всего память была похереная куда раньше, но сейчас дает о себе знать.

Для таких случаев valgind самое оно. По винду не приходилось такого дебажить.


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 17:18
Какая память-то? Одно единственное выделение памяти в коде. f создаётся парой строк раньше.
И вообще я грешу на QString. Уж больно часто с ними проблемы.


Название: Re: Неотлаживаемый код
Отправлено: Tuxford от Сентябрь 07, 2015, 17:22
Какая память-то? Одно единственное выделение памяти в коде. f создаётся парой строк раньше.
И вообще я грешу на QString. Уж больно часто с ними проблемы.
Полный код выложите.
Маловероятно что дело в QString.

PS. вот такие проблемы проблемы в большинстве случаев легко выловить с помощью юнит-тестов.


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 17:36
Вот вся функция загрузки. Больше нигде пока те классы не используются и ранее никакой код не выполняется. Просто запускается программа, нажимается кнопка OpenFile и выполняется эта функция.
Код:
int PScript::load_from_file(const QString &filename)
{
    if (filename.isEmpty()) return 1;
    // Поиск кодека
    QTextCodec *conv=QTextCodec::codecForName("UTF-8");
    if (conv==0) return 2;
    // Открытие файла
    FILE* module=NULL;
#ifdef WIN32
    module=_wfopen(filename.toStdWString().c_str(), QString("rb").toStdWString().c_str());
#else
    module = fopen(filename.toStdString().c_str(), "rb");
#endif
    if (module==NULL) return 3;
    // Переменные
    QString str;
    int count=0;
    int len=0;
    char type=0;
    if (fread(&count,sizeof(int),1,module)==0) return 4;
    this->var_count=count;
    this->global_vars=new PVariable[count];
    for (int i=0; i<count;++i)
    {
        // Имя
        if (fread(&len,sizeof(int),1,module)==0) return 5;
        if (len<1 || len>32) return 6;
        memset(this->global_vars[i].name,0,33);
        if (fread(this->global_vars[i].name,sizeof(char),len,module)==0) return 7;
        // Тип
        if (fread(&this->global_vars[i].value.type,sizeof(char),1,module)==0) return 8;
        // Размерности
        if (fread(&len,sizeof(int),1,module)==0) return 9;
        this->global_vars[i].value.arr_dim=len;
        if (len>0 &&
            fread(&this->global_vars[i].value.arr_sizes,sizeof(int),len,module)==0)
            return 10;
    }
    // Функции
    if (fread(&count,sizeof(int),1,module)==0) return 11;
    this->func_count=count;
    this->functions=new PFunct[count];
    PFunct *f=0;
    int addr=0;
    int loc_count=0;
    for (int i=0; i<count;++i)
    {
        f=&this->functions[i];
        // Адрес
        if (fread(&f->addr,sizeof(int),1,module)==0) return 12;
        if (addr<0) return 13;
        // Имя
        if (fread(&len,sizeof(int),1,module)==0) return 14;
        if (len<1 || len>32) return 15;
        memset(f->name,0,33);
        if (fread(f->name,sizeof(char),len,module)==0) return 16;
        // Тип
        if (fread(&f->ret_type,sizeof(char),1,module)==0) return 17;
        // Количество аргументов
        if (fread(&f->arg_count,sizeof(int),1,module)==0) return 18;
        if (f->arg_count>0)
        {
            if (fread(f->args,sizeof(char),f->arg_count,module)==0) return 19;
        }
        // Локальные переменные
        if (fread(&loc_count,sizeof(int),1,module)==0) return 20;
        f->local_variables_count=loc_count;
        if (loc_count>0)
        {
            f->local_variables=new PVariable[loc_count];
        }
        for (int l=0;l<loc_count;++l)
        {
            // Имя
            if (fread(&len,sizeof(int),1,module)==0) return 21;
            if (len<1 || len>32) return 22;
            memset(f->local_variables[i].name,0,33);
            if (fread(f->local_variables[i].name,sizeof(char),len,module)==0) return 23;
            // Тип
            if (fread(&f->local_variables[i].value.type,sizeof(char),1,module)==0)
                return 24;
            // Размерности
            if (fread(&len,sizeof(int),1,module)==0) return 25;
            f->local_variables[i].value.arr_dim=len;
            if (len>0 &&
                fread(&f->local_variables[i].value.arr_sizes,sizeof(int),len,module)==0)
                return 26;
        }
    }
    // Чтение ID конца заголовка и проверка его
    if (fread(&count,sizeof(int),1,module)==0) return 27;
    if (count!=12345678) return 28;
}
Сам класс скрипта прост, так как код не дописан.
Код:
class PScript
{
public:
    int var_count; PVariable *global_vars;
    int func_count; PFunct *functions;
public:
    PScript();
    int load_from_file(const QString &filename);
};


Название: Re: Неотлаживаемый код
Отправлено: Tuxford от Сентябрь 07, 2015, 17:52
Позвольте поинтересоваться, что в файле? Какое значения count? Не отрицательное случайно?


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 17:55
Значения нигде не отрицательные. На скрине даже кусок таблицы отладчика видно. В файле бинарные данные. Они на корректность проверены и соответствуют алгоритму загрузки.
Убрала сейчас вообще QString. Ничего не изменилось.


Название: Re: Неотлаживаемый код
Отправлено: Tuxford от Сентябрь 07, 2015, 18:09
Там не очевидно значение. Ради приличия можно было файл данных приатачить к сообщению.
Попробовал нормальное значение 16, никакого взлета нет. Когда данные корявые (забил тупо текст "123123421"), понятное дело что получив значение 825438769 умножив еще на сайз вашей структурки мы получаем совершенно фантастические запросы на выделение памяти. Система нас посылает сразу бросая эксцепшин с таким текстом: "std::bad_alloc".  поставьте try {} chatch(std::exception& e) {} и смотрите результат.
Одним словом проблема на рантайме.


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 18:16
Падает на выделении памяти для 4 элементов, а не мусорных. И никаких исключений не посылается, код падает с ошибкой segmentation.


Название: Re: Неотлаживаемый код
Отправлено: Tuxford от Сентябрь 07, 2015, 18:21
Слепил я ваш код:
Цитировать
#include <string>
#include <string.h>
#include <stdexcept>
#include <iostream>

#define MAX_DIMEN 510

class PValue
{
public:
    char type;
    int int_num;
    long long long_num;
    float float_num;
    double double_num;
    std::string str;
    int arr_dim;
    int arr_sizes[MAX_DIMEN]; // 510
    PValue()
    {
        type=0;
        int_num=0; long_num=0;
        float_num=0.0f; double_num=0.0f;
        arr_dim=0;
    }
};

#define STACK_SIZE MAX_DIMEN

class PVariable
{
public:
    char name[33];
    PValue value;
};
struct PFunct
{
    char name[33];
    int addr;
    char ret_type;
    int arg_count;
    char args[STACK_SIZE];   //510
    int local_variables_count;
    PVariable *local_variables; //Вот тут используется класс, указанный выше
    PFunct(){addr=0; local_variables_count=0; local_variables=0;}
};

class PScript
{
public:
    int var_count;
   PVariable *global_vars;
    int func_count;
   PFunct *functions;
   
public:
    PScript() {var_count = 0; global_vars = 0; func_count = 0; functions = 0;}
    int load_from_file(const std::string &filename);
};

int PScript::load_from_file(const std::string &filename)
{
    if (filename.empty()) return 1;
    // Поиск кодека
//    QTextCodec *conv=QTextCodec::codecForName("UTF-8");
//    if (conv==0) return 2;
    // Открытие файла
    FILE* module=NULL;
/*#ifdef WIN32
    module=_wfopen(filename.toStdWString().c_str(), QString("rb").toStdWString().c_str());
#else*/
    module = fopen(filename.c_str(), "rb");
//#endif
    if (module==NULL) return 3;
    // Переменные
//    QString str;
    int count=0;
    int len=0;
    char type=0;
    if (fread(&count,sizeof(int),1,module)==0) return 4;
    this->var_count=4;
   try
   {
    this->global_vars=new PVariable[this->var_count];
   }
   catch(std::exception& e)
   {
      std::cout << e.what();
   }
   catch(...)
   {
      std::cout << "Unknown\n";
   }
   
    for (int i=0; i<count;++i)
    {
        // Имя
        if (fread(&len,sizeof(int),1,module)==0) return 5;
        if (len<1 || len>32) return 6;
        memset(this->global_vars.name,0,33);
        if (fread(this->global_vars.name,sizeof(char),len,module)==0) return 7;
        // Тип
        if (fread(&this->global_vars.value.type,sizeof(char),1,module)==0) return 8;
        // Размерности
        if (fread(&len,sizeof(int),1,module)==0) return 9;
        this->global_vars.value.arr_dim=len;
        if (len>0 &&
            fread(&this->global_vars.value.arr_sizes,sizeof(int),len,module)==0)
            return 10;
    }
    // Функции
    if (fread(&count,sizeof(int),1,module)==0) return 11;
    this->func_count=count;
    this->functions=new PFunct[count];
    PFunct *f=0;
    int addr=0;
    int loc_count=0;
    for (int i=0; i<count;++i)
    {
        f=&this->functions;
        // Адрес
        if (fread(&f->addr,sizeof(int),1,module)==0) return 12;
        if (addr<0) return 13;
        // Имя
        if (fread(&len,sizeof(int),1,module)==0) return 14;
        if (len<1 || len>32) return 15;
        memset(f->name,0,33);
        if (fread(f->name,sizeof(char),len,module)==0) return 16;
        // Тип
        if (fread(&f->ret_type,sizeof(char),1,module)==0) return 17;
        // Количество аргументов
        if (fread(&f->arg_count,sizeof(int),1,module)==0) return 18;
        if (f->arg_count>0)
        {
            if (fread(f->args,sizeof(char),f->arg_count,module)==0) return 19;
        }
        // Локальные переменные
        if (fread(&loc_count,sizeof(int),1,module)==0) return 20;
        f->local_variables_count=loc_count;
        if (loc_count>0)
        {
            f->local_variables=new PVariable[loc_count];
        }
        for (int l=0;l<loc_count;++l)
        {
            // Имя
            if (fread(&len,sizeof(int),1,module)==0) return 21;
            if (len<1 || len>32) return 22;
            memset(f->local_variables.name,0,33);
            if (fread(f->local_variables.name,sizeof(char),len,module)==0) return 23;
            // Тип
            if (fread(&f->local_variables.value.type,sizeof(char),1,module)==0)
                return 24;
            // Размерности
            if (fread(&len,sizeof(int),1,module)==0) return 25;
            f->local_variables.value.arr_dim=len;
            if (len>0 &&
                fread(&f->local_variables.value.arr_sizes,sizeof(int),len,module)==0)
                return 26;
        }
    }
    // Чтение ID конца заголовка и проверка его
    if (fread(&count,sizeof(int),1,module)==0) return 27;
    if (count!=12345678) return 28;
}
int main(int argc, char** argv)
{
   PScript ps;
   ps.load_from_file("d:/temp/zz.z");
   return 0;
}

Вот так я сделал. Никаких меседжей (см. try catch) не было.
Пробуйте try catch. Смотрите какой ексцепшин вылетел.


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 18:23
У меня try тоже не отлавливает ничего. Код доходит до выделения памяти и отладчик завершается с ошибкой сегментации.
Не под отладчиком "В приложении обнаружена ошибка"


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 18:34
Такой код. loc_count равен 4. f валидна, пара членов ей уже присвоено, теперь надо создать и local_variables. До присваивания указатель равен нулю.
Код:
try {f->local_variables=new PVariable[loc_count];}
            catch(std::exception& e)
            {
                QMessageBox msg;
                msg.setText(QString(e.what()));
                msg.exec();
            }
            catch(...)
            {
                QMessageBox msg;
                msg.setText(QString("HZ"));
                msg.exec();
            }
Доходит до выделения и получаю:
(http://puu.sh/k36i7/3fdcb99f75.png)


Название: Re: Неотлаживаемый код
Отправлено: Tuxford от Сентябрь 07, 2015, 18:40
Оригинально. Что-то здесь не то. Попробуйте бинари нафиг удалить, так чтобы 100% все пересобралось.

PS. завел студию. Мелкософт реализовал как всегда по своему. Там креш если значение дикое. Если 4, все муркен.
PPS. Мой код с фиксами запускали? Если проблема действительно с Qt, то мой код должен заработать.


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 18:44
Бинарники  пересобрала, кьютовских классов больше в коде нет, только натив. Я уже в полном ступоре. Потом под линуксом попробую запустить.


Название: Re: Неотлаживаемый код
Отправлено: Bepec от Сентябрь 07, 2015, 20:16
Это называется лень. Нужно всего то пройти пошагово все ваши ф-ции, мониторя значения.

PS 95% ошибки программиста, 2% ОС, 2% используемых библиотек, 1% барабашки.


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 20:30
Это называется лень. Нужно всего то пройти пошагово все ваши ф-ции, мониторя значения.
А я тему создала не для того, чтобы сидеть и ждать, пока за меня всё сделают. Я в это время вообще-то как раз мониторила.
Тему создала, потому что бомбануло, надо было поделиться. Код в теме - далеко не первая тысяча строк и даже не первый десяток тысяч строк, мозг замыливается.
Проблему нашла. Она была в неявной перезаписи данных массива f
На самой неправильной записи прога не крашилась, так как по стечению обстоятельств адреса не вышли за допустимые, а вот при последующем выделении мусор в памяти давал о себе знать.
Я бы не сказала, что это тривиальная ошибка, которую отладить - пара минут.
А ошибки в коде всегда тупые, что уж поделать


Название: Re: Неотлаживаемый код
Отправлено: m_ax от Сентябрь 07, 2015, 20:43
Цитировать
Код в теме - далеко не первая тысяча строк и даже не первый десяток тысяч строк,
Ох, если там весь код подобный представленному здесь, то остаётся только сэппуку) Только Сэппуку) 


Название: Re: Неотлаживаемый код
Отправлено: akuta от Сентябрь 07, 2015, 21:11
Ох, если там весь код подобный представленному здесь, то остаётся только сэппуку) Только Сэппуку) 
Выложена тупая функция загрузки, написанная за 5 минут в костыльном варианте. Естесственно всё будет переписано нормально
А сепукку девочкам не положено  ;D


Название: Re: Неотлаживаемый код
Отправлено: Igors от Сентябрь 08, 2015, 08:52
fread выглядит очень привлекательно, раз! - и одной строкой прочитали целую структуру. А так нужно КАЖДОЕ ПОЛЕ писать (сериализовать). Но все-таки рано или поздно все приходят к выводу - да, как ни крути а надо сериализовать каждое поле, использовать операторы << и >>, да и вообще юзать потоки, напр QDataStream.

Переписывайте нормально, сейчас Вы просто теряете время на отладку кода который придется сносить. Как в том анекдоте
Цитировать
И будет "крашить" пока не купите стиральную машину "Вятка"!