DCSIMG
December 2009 - Posts - Asaf Shelly

December 2009 - Posts

Visual C++ Compiler ERROR C2016
Tuesday, December 29, 2009 5:58 PM

Compiling a C file with Visual Studio 2008 compiler I got this error:

"error C2016: C requires that a struct or union has at least one member"

I am writing this post because it is not documented, and C2016 on MSDN is defined as "A newline character was found before the closing single quotation mark of a character constant". Either it is not well documented or I don't know where to look for it. Whatever the reason I can only guess that someone else will find the same problem.

This is the cause:

struct
{
   int    u8Type;
   int    u8LenExtended;
   int   u16Length;
} Base_Request;

struct Request_Ex
{
   Base_Request Request;
   int Address;
   int Length;
};

This is the fix:

typedef struct
{
   int    u8Type;
   int    u8LenExtended;
   int   u16Length;
} Base_Request;

struct Request_Ex
{
   Base_Request Request;
   int Address;
   int Length;
};

This is over simplified intentionally.

Asaf

WinUSB .Net Component
Tuesday, December 29, 2009 9:43 AM

I have uploaded a WinUSB Component for .Net with full source code here: WinUSB .Net Component in C#.

The component comes with full source code and has the following features:

 

Pacific Software & HPC
Sunday, December 27, 2009 4:02 PM

מזה מספר שנים שחברת פסיפיק תוכנה מובילה בתחום הפיתוח המקבילי בארץ. בקרוב מיקרוסופט מוציאה את גרסת Server 2008 HPC R2 ופסיפיק מחפשת מומחי IT שמתעניינים בתחום הקמה ותחזוקה של מערכות HPC

 אסף

Verifying C++ Buffers
Sunday, December 27, 2009 10:12 AM

This post is following this post: Verifying Pointers in C++ which demonstrated the problem in testing a pointer for NULL after allocation like this:

char* ptr=new char[1];
if (NULL == ptr) // fail

There is another issue with verifying pointers for NULL. The value NULL is #defined as 0 (zero) which is agreed to be an invalid memory address. Testing a pointer to see if it is NULL means testing to see if the pointer is pointing to address zero or not. As we all know, when we allocate a buffer and then delete it we must zero the pointer. Verifying a pointer is relying on the fact that every pointer that does not point to a legal buffer is manually reset. Like this:

main()
{
   char* ptr = NULL;
   MyFunc(ptr);
   ptr = new char[20];   MyFunc(ptr);
   delete[] ptr; ptr = NULL;
   MyFunc(ptr);
}

void MyFunc(char* ptr)
{

   if (NULL == ptr) return;
   // ...do something...
}
 

You may assume that verifying the pointer in MyFunc is fine because the code is verified to make sure that every pointer is correctly initialized to zero and so if a NULL pointer is used the function is protected from it. This is not really the case. To demonstrate the problem we can look at the following scenario.

We have a class called Label. This class has several members including the text string to display. Here is the class:

class Label
{
protected:
   int X;
   int Y;
   char* text;
public:
   char* Text();
};

void UpdateDisplay()

{
   // ... more
   Label* label1 = GetSomeLabel();

   char* ptr = label1->Text();
   if (NULL == ptr) // ERROR
   // ... more
}

Now, here is the problem:

class Label
{
protected:
   int X;
   int Y;
   char text[256];
public:
   char* Text();
};

In the first version of the class the string was a pointer to a memory buffer. In this version the string is stored as part of the object. This means that in the original version the call to GetSomeLabel() in function UpdateDisplay() can return NULL if there is no label and calling the member label1->Text() will also return NULL. When we use the second version of the class we find a problem. If the call to GetSomeLabel() in function UpdateDisplay() returns NULL then the calling the member label1->Text() will return 8. Verifying the pointer for NULL will find no problem and using the macro ASSERT will also no find the bug!

void UpdateDisplay()
{
   // ... more
   Label* label1 = GetSomeLabel(); // Got label1 = NULL // label1 = 0 

   char* ptr = label1->Text();     // ptr = label1 + 8  // ptr = 8
   if (NULL == ptr) // ERROR       // can't see the problem, ignoring
   // ... more
}

When label1 is NULL the data of label1 starts at address zero; X starts at address zero, Y at address 4 which is sizeof(X), after X, and text starts at address 8. Making sure that the string text is not zero is a bug.

When we try to access the buffer text the system will get an exception. This is a CPU exception for accessing the invalid page stating on address zero. If the page size is 4KB then accessing anywhere within the range is invalid and not just address zero, so address 8 is also invalid because it is in the same page. Actually the entire block of memory ranging from address 0 and up to 64KB is marked as inaccessible for this exact reason.

The way to do this correctly is not to verify that the address is under 64K. Instead you can use the Win32 API IsBadxxxPtr. Just like checking the pointer has to be thread-safe, so does calling these API functions. It is possible that between the verification and the usage some other thread deleted the buffer if you do not make sure that this will not happen. Also this does not replace the need to reset pointers to zero after deleting them. If there is another valid buffer on the same page then the entire page is valid.

* Note that this API is not recommended by Microsoft for a parallel environment.

For code example see the wrapper code as it is used internally by the cpp files in this sample code.

 

WinUSB Read Problem
Tuesday, December 22, 2009 3:35 PM

Hi All,

I have decided to move forward from my implementation of BulkUSB.sys driver to using the formal implementation called WinUSB. It is a package of a kernel driver and a user-mode API documented as part of the MSDN library.

When I tried to do asynchronous reads I discovered two undocumented / confusing failures:

The first is GetLastError returns 997 - ERROR_IO_PENDING. This is fine for overlapped IO. The function fails and the error code means that there is more data to follow.

The second is somewhat confusing: GetLastError returns 121 - ERROR_SEM_TIMEOUT "The semaphore timeout period has expired". This means that the timeout has expired before the data was ready. The confusing part is that it looks like the call to WinUsb_ReadPipe will also fail with error code 121 if there is data in the buffer.

The read function will wait for the buffer to be full or timeout to expire. This means that the call to read will fail with error code 121 even if some data was read from the device and you must check the number of bytes read to know if read really succeeded or not. The logic behind this is that you don't call GetLastError if the function returns true.

* to set enpoint timeout use WinUsb_SetPipePolicy

 

 

by AsafShelly | with no comments
תגים:, ,
Parallel Computing Tutorial
Tuesday, December 22, 2009 11:18 AM

With some delay I am publishing a video about parallel programming. This tutorial is loaded with advanced concepts mainly dealing with parallel software design and architecture.

As some of you may know I have presented "Parallel Programming for Embedded" TechEd 2009 Europe. This is the video. There are no code samples in this presentations because there are too many languages and operating systems that it is irrelevant to show any code. Instead this presentation shows how the hardware has always been parallel and therefore it is a good source for parallel design. Windows Kernel has always been working in parallel as well, but Windows NT kernel is an embedded operating system and has its own compiler.

The concepts in this video are covered in over 20 days of lectures that I have so it is packed with many advanced concepts.

The video is currently at the home page of http://AsyncOp.com. If you can't see it there then look for it under the Video section, or under Events.

Asaf

Verifying Pointers in C++
Tuesday, December 22, 2009 10:49 AM

It is well known that C++ is having a few problems with pointers...

When we used C style malloc( ) and free( ) we verified the returned pointer. If the pointer was NULL (zero) then it was invalid and should not be used.

Going to C++ we have constructors. A constructor does not have a return value so the only way to notify the caller that the construction failed was using an exception. If my object is using an internal buffer and the system is out of memory then my constructor has to throw an out-of-memory exception.

The caller who created my object using the new operator will have to catch the exception. This is the only way to know that the creation of the object had failed. Constructors cannot return NULL because an object can also be created in the local scope and then there is no return value.

All this means that the following is a logical error:

MyClass *ptr = new MyClass(12);

if (!ptr) return(ERROR_CODE_FAIL);

There is an error because C++ will make sure that an exception is thrown in case of an error so the code flow will break before the second line and therefore the second line will only execute if the pointer has a valid value.

Here is one way to do this correctly:

MyClass *ptr = null;try { ptr = new MyClass(12); } catch(...) { ptr = NULL; }if (!ptr) return(ERROR_CODE_FAIL);

You can also look for the reserved word nothrow which is a Microsoft Visual C++ extension.

 

http://AsyncOp.com

by AsafShelly | 2 comment(s)
תגים:
Open Source Libraries for windows
Sunday, December 20, 2009 9:51 AM

Hi All,

As you can see I have upgraded the shared-source engine (see my previous post http://blogs.microsoft.co.il/blogs/asafshelly/archive/2009/04/21/sharing-my-source.aspx)

The Open-Source section in www.AsyncOp.com now has the complete collection of modules and C++ classes that I have been using for Windows. These include threading and shared memory classes, string classes, communications, graphics and more. Not exactly MFC style classes but will work with MFC.

The code is compatible with MFC, Borland C++, Managed C++, and will also work with native Win32 API.

For example the text class can open a web-page and read from it using >> operators. It can also find an HTML title by using wPage("<head>","</head>")[1]("<title>","</title>")[1]

You are welcome to use the code, parts of the code, and the dll as a library.

http://www.asyncop.com/MTnPDirEnum.aspx?treeviewPath=%5bo%5d+Open-Source%5cWinModules

Asaf