Open Watcom

High-level languages programming questions
  • andrew_programmer

    Твой код. Я так думаю. Где-то в CreateInterface. Там все структуры создаются malloc хотя это не массивы структур и их можно разместить в стеке. Любая ошибка в работе с указателями может повредить кучу после чего возможны такие трудноуловимые ошибки.
  • Твой код. Я так думаю. Где-то в CreateInterface.
    Я доработал функцию CreateInterface(). Там сейчас просто нечему разрушать указатели. Единственное из-за чего может сейчас неработать эта функция - неправильное выделение кучи malloc() -ом(если куча до этого разрушена). Даже с новой функцией CreateInterface() перестановка функции LoadSpectra() ведёт всё к тем же последствиям. Значит, если куча и разрушается, то до функции CreateInterface().
    Там все структуры создаются malloc хотя это не массивы структур и их можно разместить в стеке.
    Насколько я понимаю занесение структуры в стек с нужным выравниванием делается через #pragma pack(push,number) , где вместо number выравнивание. Я попробовал это сделать для одной структуры через #pragma pack(push,1) . Программа работала. А вот когда я такое сделал ещё для другой структуры, то программа стала вылетать. В чём я неправ ?
    И ещё вопрос. Если я занёс структуру в стек, то она там будет всё время работы программы? А если вовремя работы программы после использования структуры её нужно удалить из стека, то что делать ? Я думаю, что это как-то делается через #pragma pack(pop), но вот как - я непонял. Help в OpenWatcom-ме этого не объясняет и Help в MSVC тоже.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • В стэк сам ты её врядли заносишь, этим занимается компилер, за освобождением он тоже в состоянии сам проследить. Ты наверно не там ошибки ищешь. pop восстанивит выравнивание, дефолтное или которое было до этого (насколько я понимаю)
  • стэк сам ты её врядли заносишь, этим занимается компилер,
    Я это знаю. Только немогу понять почему у меня код вылетает. Я пробовал ставить #pragma pack(pop) после структур. Всёравно непомогает.

    Подожду ответа Serge-а. Он всё знает. :)
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • Забыл сказать. Упакованные структуры я объявляю как указатели и при этом не выделяю для них память через malloc.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • Разобрался в чём дело. При сохранении структур в стеке нужно объявлять структуры в программе как переменные и работать с ними соответственно.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • andrew_programmer
    Размещение в стеке - создание локальной переменной. Ты объявляешь указатель на структуру struct ControlButton *ButtonTrueRestore; и потом выделяешь память для неё через malloc а надо сразу создавать экземпляр структуры в стеке struct ControlButton ButtonTrueRestore. Указатель имеет смысл если это будет массив заранее неизвестного размера. Другой пример
    char *names_of_bookmarks1[]={"SINGLET","DOUBLET","SIXTET","P(H)","OTHER"};
    Этот массив указателей локальный и компилятор честно создаёт его в стеке, копирует туда адреса строк, хотя в этом нет необходимости. Объяви эти массивы static. Это уменьшит размер кода и упростит его. Явных приведений типа лучше избегать. Если InfoForButton.text хранит указатель на строку то пусть это будет char *, а не unsigned int. Ещё одна проблема огромное количество предупреждений при компиляции. Среди них могут быть действительно важные но они просто тонут в общей массе.
    Этот код проверяет кучу. У меня всё нормально, значит ошибка в другом месте.

    Code: Select all

        switch( _heapchk() ) {
        case _HEAPOK:
          printf( "OK - heap is good\n" );
          break;
        case _HEAPEMPTY:
          printf( "OK - heap is empty\n" );
          break;
        case _HEAPBADBEGIN:
    
          printf( "ERROR - heap is damaged\n" );
          break;
        case _HEAPBADNODE:
          printf( "ERROR - bad node in heap\n" );
          break;
        }
  • Serge

    Спасибо за советы.
    Ты объявляешь указатель на структуру struct ControlButton *ButtonTrueRestore; и потом выделяешь память для неё через malloc а надо сразу создавать экземпляр структуры в стеке struct ControlButton ButtonTrueRestore. Указатель имеет смысл если это будет массив заранее неизвестного размера.
    Я так и сделал вчера - работает.
    Другой пример
    char *names_of_bookmarks1[]={"SINGLET","DOUBLET","SIXTET","P(H)","OTHER"};
    Этот массив указателей локальный и компилятор честно создаёт его в стеке, копирует туда адреса строк, хотя в этом нет необходимости. Объяви эти массивы static. Это уменьшит размер кода и упростит его.
    Сделаю.
    Ещё одна проблема огромное количество предупреждений при компиляции. Среди них могут быть действительно важные но они просто тонут в общей массе.
    При самой первой компиляции их было в разы больше. Но я просмотрел каждое сообщение компилятора. И оставил только те, которые неважны(типа "ненайден прототип для функции"). Там ещё есть сообщения про переопределения функций libGUI, но как сделать, чтобы он правильно понял идею - непонятно. Но главное, что код с функциями libGUI работает как и должно работать.
    Этот код проверяет кучу. У меня всё нормально, значит ошибка в другом месте.


    Только вот в каком другом... Но я всётаки хочу добить эту проблему.
    Мне хочется сделать OpenWatcom основным инструментом для разработки научных программ для KolibriOS. Тем более что, как показывают тесты, моя научная программа, скомпилированная Watcom-ом работает на 40% быстрее, чем скомпилированная GCC. Причём в варианте с GCC уже первый уровень оптимизации приводит к неработоспособности программы, а у OpenWatcom-а с этим всё впорядке.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • Serge

    Ха!
    Не там собака была зарыта, где её искали! (поговорка)
    Я нашёл истинную причину! :D :D :D

    И так, как было дело.
    Я почистил код программы, так что компилятору просто не к чему было придраться. А код всёравно глючил. Проблема возникала при открытии файла для сохранения результатов вычислений. Причём результаты вычислений P(H) сохрнялись(там открывалось 2 файла), а результаты дискретной обработки нет(там один файл открывался).
    Уменя компиляция происходила с опцией "fastest possible cod" , а под стек выделялось 10Kb. Я решил скомпилировать код вообще без оптимизации. Скомпилировал. Попробовал вычислить программой P(H) - работает. Попробывал обработать дискретный спектр - вылетает уже на этапе старта алгоритма. И при этом на доске отладки появляется сообщение "stack overflow"(переполнение стека). Я выделил под стек 16 Kb -мало. Выделил 64Kb - код заработал без ошибок(нет глюков!).

    Большое спасибо за советы!
    Теперь можно по нормальному программировать.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • andrew_programmer wrote:Разобрался в чём дело. При сохранении структур в стеке нужно объявлять структуры в программе как переменные и работать с ними соответственно.
    Обычный прикол С

    struct A {
    int a;
    int b;
    };
    struct A a;
    struct A b;
    A *p = (A*)malloc(sizeof(A));
    free(p);
    return 0;


    При создании переменной в стеке нужно указывать слово struct. Это в плюсах можно этого не делать :) а в си будет плохо.
    Если бы строители строили здания, так же как программисты пишут программы первый же залетевший дятел разрушил бы цивилизацию.
  • Who is online

    Users browsing this forum: No registered users and 5 guests