Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

Arithmetic overflows in C#/C/C++

Иногда самая банальная вещь может быть невероятно полезной. К примеру, как бы Вы решили проблему переполнения в результате арифметических операций, скажем, на языке C/C++? Уверен, пришлось бы анализировать операнды перед операций в поиске возможного переполнения, что есть не очень тривиальная задача. Еще один недостаток такого решения - производительность, анализ будет дороже самой операции. Конечно, можно использовать ассемблерные вставки типа _asm jo OverflowedLabel после каждой операции, но это скорее маразм. Я хочу заметить, что язык ассемблера позволяет постфактум проверять флаг переполнения последней арифметической операции.

Язык C#, IL код и CLR позволяют легко выявлять переполнения с помощью т.н. checked секций кода. Одноименное ключевое слово языка C# определяет блок кода в котором переполнения приводят к исключению OverflowException. Реализация проста до безобразия - JIT вставляет операцию jo SomeAddr после каждой операции внутри блока checked, а по адресу SomeAddr находится одна единственная инструкция - call clr!JIT_Overflow.

Интересно, а многие разработчики вообще следят за такими вещами? Обрабатываете ли вы возможные переполнения? Приходит ли вообще на ум, что это может быть проблемой?

Visual Studio 2012 Update 3 RC 2

Download Visual Studio 2012 Update 3 RC 2.

Mauritius Beachcomber Royal Palm

Вот сюда отправляемся в конце сентября. Отчет по приезду. Завидуйте! :)

Xbox 360 Wireless Controller for Windows

Купил себе Xbox 360 Wireless Controller for Windows, для ПК. Некоторые игры засияли во всей красе, например заброшенный почти сразу Prince of Persia Forgotten Sands. Невероятно удобный манипулятор! Втыкнул ресивер в USB, засунул батарейки в устройство, включил - все, можно играть.

Xbox 360 Wireless Controller for Windows

Visual C++ concurrency runtime bug

#include <thread>
#include <mutex>
#include <condition_variable>
 
std::mutex m1;
std::mutex m2;
 
std::condition_variable e1;
std::condition_variable e2;
 
void t1()
{   
   for (;;) {
      {
      std::lock_guard<std::mutex> lg(m1);
      e1.notify_one();
      }
      std::unique_lock<std::mutex> m2Lock(m2);
      e2.wait_for(m2Lock, std::chrono::milliseconds(15));
   }
}
 
void t2()
{   
   for (;;) {
      {
      std::lock_guard<std::mutex> lg(m2);
      e2.notify_one();
      }
      std::unique_lock<std::mutex> m1Lock(m1);
      e1.wait_for(m1Lock, std::chrono::milliseconds(15));
   }
}
 
int _tmain(int argc, _TCHAR* argv[])
{
   const auto hc = std::thread::hardware_concurrency();
   std::thread thread1(&t1);
   std::thread thread2(&t2);
   thread1.join();
   thread2.join();
   return 0;
}
 

Вот такая простая программа падает со следующим сообщением:

Unhandled exception at 0x0000000077A32782 (ntdll.dll) in Win32ConInv.exe: 0xC000000D: An invalid parameter was passed to a service or function.

Stack:

 	ntdll.dll!string "Enabling heap debug options\n"()	Unknown
>	msvcr110d.dll!__crtWaitForThreadpoolTimerCallbacks(_TP_TIMER * pti, int fCancelPendingCallbacks) Line 539	C
 	msvcr110d.dll!Concurrency::details::DeleteAsyncTimerAndUnloadLibrary(_TP_TIMER * timer) Line 696	C++
 	msvcr110d.dll!Concurrency::details::TimedSingleWaitBlock::destroyTimer(bool waitForOutstandingCallback) Line 457	C++
 	msvcr110d.dll!Concurrency::details::TimedSingleWaitBlock::Satisfy(Concurrency::Context * * pContextOut, Concurrency::details::EventWaitNode * pNode) Line 484	C++
 	msvcr110d.dll!Concurrency::details::EventWaitNode::Satisfy(Concurrency::Context * * pContextOut) Line 330	C++
 	msvcr110d.dll!Concurrency::details::_Condition_variable::notify_one() Line 645	C++
 	msvcp110d.dll!do_signal(_Cnd_internal_imp_t * * cond, int all) Line 68	C++
 	msvcp110d.dll!_Cnd_signal(_Cnd_internal_imp_t * * cond) Line 84	C++
 	Win32ConInv.exe!std::_Cnd_signalX(_Cnd_internal_imp_t * * _Cnd) Line 108	C++
 	Win32ConInv.exe!std::condition_variable::notify_one() Line 51	C++
 	Win32ConInv.exe!t1() Line 21	C++
 	Win32ConInv.exe!std::_Bind<1,void,void (__cdecl*const)(void),std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Line 1152	C++
 	Win32ConInv.exe!std::_LaunchPad >::_Run(std::_LaunchPad > * _Ln) Line 196	C++
 	Win32ConInv.exe!std::_LaunchPad >::_Go() Line 188	C++
 	msvcp110d.dll!_Call_func(void * _Data) Line 52	C++
 	msvcr110d.dll!_callthreadstartex() Line 354	C
 	msvcr110d.dll!_threadstartex(void * ptd) Line 337	C
 	kernel32.dll!BaseThreadInitThunk()	Unknown
 	ntdll.dll!RtlUserThreadStart()	Unknown

А вот и дефект на Microsoft Connect со статусом Closed. Stephan T. Lavavej обещает the fix will be available in the next release of our C++ Standard Library implementation, 12/17/2012. Дефект открыт 9/13/2012, сейчас 04/28/2013. Пиздец!

Copyright 2007-2011 Chabster