Моя программа прерывается, потому что я использую new в одном потоке и удаляю в другом?

#c #multithreading

#c #многопоточность

Вопрос:

Я считываю данные с com-порта. Поскольку я не знаю, когда поступают данные, я непрерывно читаю в потоке.

Когда я прочитаю достаточно байтов, я сообщаю об этом основному потоку, отправляя сообщение с указателем на строку:

 msg[i] = '';
completeMsg = new char[i];
strcpy(completeMsg, msg);
PostMessage(hDlg, BT_MSG, NULL, (LPARAM) completeMsg);
i = 0;
  

Ответ основного потока на это сообщение:

 case BT_MSG:
{
    char* msg = (char*) lParam;
    ShowMsg(msg);
    delete [] msg;
    break;
}
  

Но похоже, что удаление в этом потоке запрещено, потому что я получаю эту ошибку, когда я перехожу к строке удаления:

Windows запустила точку останова в SPO.exe.

Это может быть связано с повреждением кучи, что указывает на ошибку в SPO.exe или любой из загруженных им DLL.

Это также может быть связано с тем, что пользователь нажимает F12 во время SPO.exe имеет фокус.

Окно вывода может содержать дополнительную диагностическую информацию.

Должен ли я использовать какую-либо глобальную переменную или отправить сообщение обратно, чтобы поток чтения обработал удаление? В нем нет atm с циклом обмена сообщениями, поэтому я бы предпочел не добавлять его только для этого.

Комментарии:

1. Разве это не должно быть new char [i 1]?

2. Так и должно быть -.- и сейчас это работает идеально. 🙂 Не знал, что это приведет к повреждению кучи. ^^’

Ответ №1:

Вы должны иметь возможность использовать new в одном потоке и delete в другом, при условии, что вы ссылаетесь на многопоточную библиотеку времени выполнения вашего компилятора.

Однако, похоже, что у вас действительно переполнен буфер. Вы завершаете нулевым значением msg с помощью msg[i]=0 , но выделяете только i байты — вам, вероятно, нужно new char[i 1] .

Комментарии:

1. Мне интересно, действительно ли библиотеки MT переопределяют new и delete . Конечно, каждая операция должна быть атомарной, но виртуальная адресация остается неизменной…

2. Спасибо, впервые использую threads, поэтому я действительно думал, что проблема была более сложной: P

Ответ №2:

Можно удалить память, выделенную в другом потоке, предполагая, что все правильно синхронизировано. В вашем случае поток вашего COM-порта не использует выделенный указатель после postMessage, поэтому удаление в основном потоке нормально.

Итак, мне интересно, получаете ли вы «обычное» повреждение кучи, которое не имеет ничего общего с потоковой обработкой. Проблема может быть в strcpy зависимости от того, что именно i означает. Помните, что strcpy это приведет к записи завершающего нулевого символа. Вы, вероятно, хотите:

 completeMsg = new char[i 1];