Russian Qt Forum
Май 17, 2024, 21:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Неотлаживаемый код  (Прочитано 7415 раз)
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.
Вот результат дебаггера:

Я не понимаю, что я делаю не так. Дебаггер не может найти конкретное место падения даже, последняя строка, до которой он доходит по шагам, это вот та строка с new.
Записан
Tuxford
Гость
« Ответ #1 : Сентябрь 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 самое оно. По винду не приходилось такого дебажить.
« Последнее редактирование: Сентябрь 07, 2015, 17:21 от Tuxford » Записан
akuta
Гость
« Ответ #2 : Сентябрь 07, 2015, 17:18 »

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

Какая память-то? Одно единственное выделение памяти в коде. f создаётся парой строк раньше.
И вообще я грешу на QString. Уж больно часто с ними проблемы.
Полный код выложите.
Маловероятно что дело в QString.

PS. вот такие проблемы проблемы в большинстве случаев легко выловить с помощью юнит-тестов.
« Последнее редактирование: Сентябрь 07, 2015, 17:25 от Tuxford » Записан
akuta
Гость
« Ответ #4 : Сентябрь 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);
};
Записан
Tuxford
Гость
« Ответ #5 : Сентябрь 07, 2015, 17:52 »

Позвольте поинтересоваться, что в файле? Какое значения count? Не отрицательное случайно?
Записан
akuta
Гость
« Ответ #6 : Сентябрь 07, 2015, 17:55 »

Значения нигде не отрицательные. На скрине даже кусок таблицы отладчика видно. В файле бинарные данные. Они на корректность проверены и соответствуют алгоритму загрузки.
Убрала сейчас вообще QString. Ничего не изменилось.
Записан
Tuxford
Гость
« Ответ #7 : Сентябрь 07, 2015, 18:09 »

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

Падает на выделении памяти для 4 элементов, а не мусорных. И никаких исключений не посылается, код падает с ошибкой segmentation.
« Последнее редактирование: Сентябрь 07, 2015, 18:18 от akuta » Записан
Tuxford
Гость
« Ответ #9 : Сентябрь 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. Смотрите какой ексцепшин вылетел.
Записан
akuta
Гость
« Ответ #10 : Сентябрь 07, 2015, 18:23 »

У меня try тоже не отлавливает ничего. Код доходит до выделения памяти и отладчик завершается с ошибкой сегментации.
Не под отладчиком "В приложении обнаружена ошибка"
Записан
akuta
Гость
« Ответ #11 : Сентябрь 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();
            }
Доходит до выделения и получаю:
Записан
Tuxford
Гость
« Ответ #12 : Сентябрь 07, 2015, 18:40 »

Оригинально. Что-то здесь не то. Попробуйте бинари нафиг удалить, так чтобы 100% все пересобралось.

PS. завел студию. Мелкософт реализовал как всегда по своему. Там креш если значение дикое. Если 4, все муркен.
PPS. Мой код с фиксами запускали? Если проблема действительно с Qt, то мой код должен заработать.
Записан
akuta
Гость
« Ответ #13 : Сентябрь 07, 2015, 18:44 »

Бинарники  пересобрала, кьютовских классов больше в коде нет, только натив. Я уже в полном ступоре. Потом под линуксом попробую запустить.
Записан
Bepec
Гость
« Ответ #14 : Сентябрь 07, 2015, 20:16 »

Это называется лень. Нужно всего то пройти пошагово все ваши ф-ции, мониторя значения.

PS 95% ошибки программиста, 2% ОС, 2% используемых библиотек, 1% барабашки.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.104 секунд. Запросов: 20.