Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: SOS. Ошибка при запонении списка из процедуры обработки прерывания  (Прочитано 14764 раз)
0 Пользователей и 6 Гостей смотрят эту тему.
Alice1144
Гость
« : 03-03-2009 18:18 » 

Подскажите в чем моя ошибка и откуда берется ошибка "Null pointer assignment".
Программа по прерыванию от таймера заполняет список, в основном модуле читает список и выводит на экран. Выводит:
 10 10 10 10 10 10 10 10 10 10 Null pointer assignment
Должно быть:
 1 2 3 4 5 6 7 8 9 10
Текст программы:
Код:
//#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <iostream.h>
//#include <alloc.h>
#include <stdlib.h>
//#include <bios.h>;
//#include <process.h>

#ifdef __cplusplus
    #define __CPPARGS ...
#else
    #define __CPPARGS
#endif

struct BuffList{
unsigned int VK;
struct BuffList *next;
} start, *node, *first, *last;

int looping = 1;
void interrupt get_out(__CPPARGS);
void interrupt (*oldfunc)(__CPPARGS);

void main(void)
{ clrscr();
  start.next = NULL;
  node = first = last= &start;
  oldfunc  = _dos_getvect(0x1c);
  _disable();
  _dos_setvect(0x1c,get_out);
  _enable();
  sleep(2); //ждем пока заполнится список
  first=first->next;
  for (char k=1;k<11;k++)
  {
    node=first;
    cout<<node->VK<<"\r\n";
    first=node->next;
    //free(node);
  }
  _disable();
  _dos_setvect(0x1c,oldfunc);
  _enable();
}

void interrupt get_out(__CPPARGS)  //прерывание от часов 18 раз в секунду
{ if (looping>10) return;
  last->next =(struct BuffList*)malloc(sizeof(struct BuffList));
  last=last->next;
  last->VK=looping++;
  last->next=NULL;
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 03-03-2009 18:37 » 

насчёт
Null pointer assignment

наверное, выполняется нечто вроде этого:

const char* p=0;
cout<<p;
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 03-03-2009 18:43 » 

цикл
Код:
  for (char k=1;k<11;k++)
  {
    node=first;
    cout<<node->VK<<"\r\n";
    first=node->next;
    //free(node);
  }

насчёт всех десяток - значит действительно там они. Ошибка в другом месте. А тут ошибка такая, что нет проверки на 0 указателя, вот так красивее:

Код:
  first=first->next;
  for(;first;)
  {
    node=first;
    cout<<node->VK<<"\r\n";
    first=node->next;
  }
Записан

Alice1144
Гость
« Ответ #3 : 03-03-2009 19:06 » 

насчёт
Null pointer assignment
ошибка вылазит после окончания всех команд в main на выходе из программы.

Насчет десяток. Проанализировав в отладчике вижу, что создается первый элемент списка и он же ссылается на самого себя, в нем меняеется только значение VK (сохраняется последняя 10). Хотя в обработке прерывания
Цитата
void interrupt get_out(__CPPARGS)  //прерывание от часов 18 раз в секунду
{ if (looping>10) return;
  last->next =(struct BuffList*)malloc(sizeof(struct BuffList));
  last=last->next;
  last->VK=looping++;
  last->next=NULL;
}
прописано что каждый элемент списка ссылается на следуюший. Как устранить ошибку непонятно.
Из-за этого неправильно и считываются данные
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 03-03-2009 19:24 » 

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

Как исправить ошибку. Сначала надо узнать, что должно получиться в итоге Улыбаюсь

предполагаю, что
Код:
void interrupt get_out(__CPPARGS)  //прерывание от часов 18 раз в секунду
{
  if (looping>10) return;
  struct BuffList* a_new =(struct BuffList*)malloc(sizeof(struct BuffList));

  if(!first)
  {
    first=a_new;
  }

  last=a_new;
  last->VK=looping++;
  last->next=NULL;
}
...
Код:
//распечатка
  struct BuffList* curr=first;
  for(;curr;)
  {
    cout<<curr->VK<<"\r\n";
    curr=curr->next;
  }
Записан

Alice1144
Гость
« Ответ #5 : 03-03-2009 21:20 » 

это МК ? Или компьютер ?
Сначала надо узнать, что должно получиться в итоге
Это комп c TurboC++3.
В итоге должно быть 1 2 3 4 5 6 7 8 9 10
В более общем случае будет прерывание от LPT (с частотой несколько кГц), чтение из него, запись в BuffList, а параллельно чтение из BuffList и обработка данных

Проверил Ваши предложения. Ваша обработка прерывания дает те же результаты.
А распечатка
Код:
//распечатка
  struct BuffList* curr=first;
  for(;curr;){}
вылетает не входя в цикл.

Вставлял текст из обработки прерывания в main (заполнял циклом) все работает.
Предполагаю, что почему-то неправильно работает malloc при работе с прерыванием.
Жду еще предложений.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 04-03-2009 04:57 » 

хм...
1) проверять надо не мои предположения, а свою логику
2) неинициализирован first.

Код:
void main(void)
{
  clrscr();
  //инициализация
  first = 0;


попробуй вот такую структуру программы
Код:
//#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <iostream.h>
//#include <alloc.h>
#include <stdlib.h>
//#include <bios.h>;
//#include <process.h>

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

struct BuffList
{
unsigned int VK;
BuffList* next;

BuffList()
{
VK=0;
next=0;
}
};

struct s_array
{
BuffList* first;//первый элемент списка
BuffList** new_next;//указатель на последний, пустой элемент списка
int looping;

s_array():
{
first=0;
new_next=0;
looping=1;
}

~s_array()
{
new_next=0;

//чистим память
BuffList* nextToDel=0;
BuffList* currToDel=first;
for(;currToDel;)
{
nextToDel=currToDel->next;
free currToDel;
}
}

BuffList* AddNew()
{
if (looping>10) return 0;

if(!new_next)
{
new_next=&first;
}

*new_next=(struct BuffList*)malloc(sizeof(struct BuffList));

BuffList* result=*new_next;
new_next=&new_next->next;

result->VK=looping++;
return result;
}

//распечатка
void Print() const
{
BuffList* curr=first;
for(;curr;)
{
cout<<curr->VK<<"\r\n";
curr=curr->next;
}
}
};

s_array MyArray;


void interrupt get_out(__CPPARGS);
void interrupt (*oldfunc)(__CPPARGS);

void main(void)
{
clrscr();

oldfunc=_dos_getvect(0x1c);

_disable();
_dos_setvect(0x1c,get_out);
_enable();

//ждем пока заполнится список
sleep(1000);

//распечатка
MyArray.Print();

_disable();
_dos_setvect(0x1c,oldfunc);
_enable();
}

void interrupt get_out(__CPPARGS)  //прерывание от часов 18 раз в секунду
{
MyArray.AddNew();
}

(не тестировал)
« Последнее редактирование: 04-03-2009 04:59 от Алексей1153++ » Записан

Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 04-03-2009 07:14 » 

хм, использовать heap  прерываниях не есть хорошо, даже если в однозадачной ОС. Передай в прерывание статический массив.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Alice1144
Гость
« Ответ #8 : 06-03-2009 18:12 » 

Вы писали
Код:
	BuffList* AddNew()
{
if (looping>10) return 0;

if(!new_next)
{
new_next=&first;
}

*new_next=(struct BuffList*)malloc(sizeof(struct BuffList));

BuffList* result=*new_next;
new_next=&new_next->next;

result->VK=looping++;
return result;
}
Извините, что пропал надолго: сдох интернет.
Проверить Вашу версию проги не получается, вылазит ошибка на строке:
   new_next=&new_next->next;
И что-то мне не удается ее обойти.

Но зато заработала моя первая версия проги:
заменил sleep(1) на delay(1000) и после этого получил ожидаемый результат.
Почему sleep(1) глючит не очень понятно, может он тоже использует это прерывание и конфликтует.

Спасибо за содействие.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 06-03-2009 18:17 » 

а, ну да,

new_next=new_next->next;
Записан

Рыжий Тигра
Гость
« Ответ #10 : 27-04-2009 09:49 » 

Alice1144, malloc() изнутри таймерного прерывания - оригинально. Улыбаюсь Уверен, что при таком подходе никогда не прервёшь DOS'овую функцию (ту же sleep())? А ведь DOS ни разу не реентерабельный! Выделяй массив заранее, до _dos_setvect()'а!
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 27-04-2009 14:17 » new

Рыжий Тигра, не всё так уж страшно, если: 1) из под перегрузившего прерывание процесса не запускаются другие, 2) процесс не являтся TSR.

Проблема может быть только в том, что внутри malloc нет средств синхронизации основного потока команд, и потока команд, возникающего при срабатывании прерывания.

Тогда надо написать свою функцию-обёртку malloc, которая гарантирует последовательное срабатывание malloc в двух потоках. В простейшем случае функциями enable и disable блокировки прерываний из dos.h.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines