473,811 Members | 2,240 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Defeating Optimisation for memcmp()

Please consider the following code fragment. Assume UINT32 is a typedef
suitable for defining variables of 32 bits, and that ui32 is initialised.

UINT32 ui32;
/* ... */
/* assume ui32 now is holding a value in uc's range */
unsigned char uc = (unsigned char) ui32; /* tell Lint you know target
type is smaller */
cmos->uc = uc;

/* Check the CMOS write was successful */
/* NOTE: I know third arg evals to 1, but sizeof is used for readability
*/
if (memcmp(cmos->uc, &uc, sizeof(unsigned char)) != 0)
/* CMOS write failed */

I would expect a decent compiler to optimize away the memcmp(). Would you
agree that this change will ensure the memcmp is not optimized away?:

UINT32 ui32;
/* ... */
/* assume ui32 now is holding a value in uc's range */
volatile unsigned char uc = (unsigned char) ui32; /* tell Lint you know
target type is smaller */
cmos->uc = uc;
/* Check the CMOS write was successful */
if (memcmp(cmos->uc, &uc, sizeof(unsigned char)) != 0)
/* CMOS write failed */

Is a call to a library function (memcmp) less likely to be optimised away
than use of relational operators (a) when one of the operands is volatile,
and (b) when neither are volatile?

For example,

if ( cmos->uc != uc )
/* CMOS write failed */

compared to

if (memcmp(cmos->uc, &uc, sizeof(unsigned char)) != 0)
/* CMOS write failed */

Thank-you in advance.

--
Martin

Nov 10 '07
39 3941
Ben Pfaff wrote:
CBFalconer <cb********@yah oo.comwrites:
>Ben Pfaff wrote:
.... snip ...
>>
>>This statement is given in the context of qualifiers on types,
not qualifiers on pointers. I think that this is intended to
mean that the compiler is not obligated to store const objects
in read-only memory, and that it is not obligated to put
volatile objects in a special section of memory either.

The following was my attempt to test incrementing of a void*. I
think I can imagine situations where this ability would be useful
to bypass pointer incrementation. [...]

I am struggling to understand how this is anything but a non
sequitur. Can you explain?
I have to admit I am confused myself. :=) As I vaguely recall, I
had some ideas about exploring some crevice in your statement, but
after the fact I can't see it. However, my sample (that you
snipped) stands, and should maybe be considered.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home .att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 21 '07 #21
Martin wrote:
On Nov 21, 1:30 pm, Eric Sosman <esos...@ieee-dot-org.invalidwrot e:
> You have been told, several times and by several people,
that it is an error to pass a pointer to volatile data to a
function that isn't aware of that volatility. What have you
done with this carefully-explained information? You ignore
it, that's what, and you pass pointers to volatile data to
memcpy() and memcmp(), functions unaware of the volatility.

I give up.

Don't give up, the advice is appreciated. If I *appear* to be ignoring
the advice it's because there is something I am not understanding.

As I explained in my last post, I am passing a volatile pointer to non-
volatile data, I am not passing a pointer to volatile data; therefore,
the data dereferenced by both memcmp() and memcpy() are not volatile.
I think the distinction is important and I explained my rationale for
doing so in the message. So why is it still wrong?
If that's what you think you're doing, your declaration is incorrect. Change
volatile char *parr = arr;

into

char * volatile parr = arr;
Nov 21 '07 #22
On Nov 21, 3:37 pm, James Kuyper <jameskuy...@ve rizon.netwrote:
If that's what you think you're doing, your declaration is incorrect. Change

volatile char *parr = arr;

into

char * volatile parr = arr;
But that's exactly what I've done, albeit in the form:

. . .
CMOSTYPE * volatile pcmos = &cmos;
. . .

--
Martin
Nov 21 '07 #23
CBFalconer <cb********@yah oo.comwrites:
The following was my attempt to test incrementing of a void*. I
think I can imagine situations where this ability would be useful
to bypass pointer incrementation. BTW, cc is shorthand for:
gcc -W -Wall -ansi -pedantic
and accesses gcc 3.2.1.

[1] c:\c\junk>cat junk.c
#include <stdio.h>

int main(void) {
void *p, *pb;
char by;

p = &by;

pb = p++;
if (pb == p) puts("++ uses sizeof void* == 0");
else puts("No luck here");
return 0;
}
I'm not sure what you're hoping to demonstrate here. The size of
an incomplete type cannot be taken in ISO C, and GCC with
-pedantic amply demonstrates that by giving the required
diagnostic. That GCC then allows the program to compile to an
executable is not really a kindness.

The situation when GCC is run without -pedantic is a little
different, but GCC is not an ISO C compiler in that case.
--
int main(void){char p[]="ABCDEFGHIJKLM NOPQRSTUVWXYZab cdefghijklmnopq rstuvwxyz.\
\n",*q="kl BIcNBFr.NKEzjwC IxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+= strchr(p,*q++)-p;if(i>=(int)si zeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Nov 21 '07 #24
Martin wrote:
On Nov 21, 3:37 pm, James Kuyper <jameskuy...@ve rizon.netwrote:
>If that's what you think you're doing, your declaration is incorrect. Change

volatile char *parr = arr;

into

char * volatile parr = arr;

But that's exactly what I've done, albeit in the form:

. . .
CMOSTYPE * volatile pcmos = &cmos;
I searched back to the message you sent with the header:

Date: Tue, 20 Nov 2007 22:41:27 -0000

In that message, you declared parr exactly as indicated above. For some
reason I skipped over the one with the header

Date: Wed, 21 Nov 2007 03:27:10 -0800 (PST)

With that declaration, the problem is indeed fixed. pcmos->s is not a
volatile object, and therefore doesn't violate 6.7.3p5. For precisely
the same reason, it doesn't achieve your goal of preventing a compiler
from optimizing away the memcmp() call.
Nov 21 '07 #25
On Nov 21, 4:05 pm, James Kuyper <jameskuy...@ve rizon.netwrote:
With that declaration, the problem is indeed fixed. pcmos->s is not a
volatile object, and therefore doesn't violate 6.7.3p5. For precisely
the same reason, it doesn't achieve your goal of preventing a compiler
from optimizing away the memcmp() call.
Thanks for your response.

Surely the fact that pcmos is now a volatile pointer prevents the
compiler from optimising away the memcmp because the compiler won't
know at compile-time that pcmos won't change between the memcpy and
the memcmp?

--
Martin
Nov 21 '07 #26
Martin <ma************ @which.netwrite s:
On Nov 21, 1:13 am, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
>You haven't changed anything as far as the constraint violation on the
call to memcmp is concerned.
<snip>
>
OK, thanks for the response.
<snip>
What follows is a solution, based on the previous comments in this
thread. As far as I can tell it looks OK. Obviously, if anyone on
c.l.c. thinks differently, I'd be grateful for the comments.

typedef struct {
...
somestruct s;
...
} CMOSTYPE;

CMOSTYPE cmos;

...

/* Create a volatile pointer to the cmos structure */
CMOSTYPE * volatile pcmos = &cmos;
somestruct s;

/* Assign some values to the members of s */

...

/* Copy s into the cmos structure */
memcpy(&pcmos->s, &s, sizeof(pcmos->s));

/* Check that the CMOS write succeeded */
if (memcmp(&pcmos->s, &s, sizeof(pcmos->s)) != 0)
/* Write failed */
You have just switched the volatile property to something else. The
pointer is now volatile (probably not true) so that call is now OK but
can be optimised away is the compiler sees fit. There is no option
but to mark the thing that is volatile as volatile. If you can't do
that for some reason then I can't see a solution.

--
Ben.
Nov 21 '07 #27
On Nov 21, 4:25 pm, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
You have just switched the volatile property to something else. The
pointer is now volatile (probably not true) so that call is now OK but
can be optimised away is the compiler sees fit. There is no option
but to mark the thing that is volatile as volatile. If you can't do
that for some reason then I can't see a solution.

Thanks for the response Ben.

Your solution (of making the CMOS structure volatile) will only work
(as others here have pointed out) in the case where the item I am
writing and verifying in the cmos structure can be compared with a
simple ==. Where I write a structure such as a date/time (using
memcpy) I need to use memcmp to check that it wrote properly and I
cannot do so if the target is volatile (or if I am pretending it is).

--
Martin
Nov 21 '07 #28
In article
<be************ *************** *******@d61g200 0hsa.googlegrou ps.com>,
Martin <ma************ @which.netwrote on Wednesday 21 Nov 2007 10:55
pm:
On Nov 21, 4:25 pm, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
>You have just switched the volatile property to something else. The
pointer is now volatile (probably not true) so that call is now OK
but
can be optimised away is the compiler sees fit. There is no option
but to mark the thing that is volatile as volatile. If you can't do
that for some reason then I can't see a solution.


Thanks for the response Ben.

Your solution (of making the CMOS structure volatile) will only work
(as others here have pointed out) in the case where the item I am
writing and verifying in the cmos structure can be compared with a
simple ==. Where I write a structure such as a date/time (using
memcpy) I need to use memcmp to check that it wrote properly and I
cannot do so if the target is volatile (or if I am pretending it is).
Compare member by member individually.

Nov 21 '07 #29
In article <be************ *************** *******@d61g200 0hsa.googlegrou ps.com>
Martin <ma************ @which.netwrote :
>(... making the CMOS structure volatile) will only work
(as others here have pointed out) in the case where the item I am
writing and verifying in the cmos structure can be compared with a
simple ==. Where I write a structure such as a date/time (using
memcpy) I need to use memcmp to check that it wrote properly ...
Using memcmp() is rather likely to fail anyway, depending on
the target architecture.

Suppose memcmp() is a typical assembly-language "optimized" version,
that checks the alignment of its incoming pointers and the sizes
of the regions to compare. If the size is large enough (at least
4 or 8 bytes) and the addresses are properly aligned, it does, in
effect, the assembly equivalent of the following C code:

unsigned char *left, *right; /* then initialized from parameters */
size_t len; /* initialized from parameter */

if (properly_align ed) {
while (len >= sizeof(int) && *(int *)left == *(int *)right)
left += sizeof(int), right += sizeof(int), len -= sizeof(int);
}
while (len) {
if (*left != *right)
return *left < *right ? -1 : 1;
left++, right++, len--;
}
return 0;

Now, on a lot of hardware, *(unsigned char *)addr does a 1-byte
read on the bus, which is what is required to access an EEPROM
device; but *(int *)addr does a 4-byte read on the bus. If a 4-byte
read reaches the EEPROM ("CMOS") hardware, an incorrect value is
read from the device, or an exception ("bus error" or similar) is
delivered to the CPU.

Not all hardware works like this[%], and sometimes memcmp() really
can be used directly against "hardware memory", but exceptions
are common enough (in my experience anyway) to assume the worst,
and avoid memcmp() here.

[% Two particularly bizarre examples occur with 8-bit hardware
attached to "32-bit-only" CPUs. Here, "load byte" does a 32-bit
bus access, or there is no separate "load byte" instruction, so
the hardware designer takes one of two approaches. Either every
8-bit byte is placed on a 32-bit boundary, so that *(int *)addr is
0x000000NN or 0xNN000000 depending on endian-ness -- and sometimes
the 00s are FFs instead, or are duplicates of the NN byte; or,
instead, the 32-bit access is put on hold while the adapter does
four 8-bit accesses so as to "construct" the full 32 bit value,
which is then placed on the data bus. In this second case, it
really *can* be good idea to use 32-bit operations to access the
device -- typically to copy the entire ROM contents to RAM for
faster reference.]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 21 '07 #30

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

16
4561
by: rajkumar | last post by:
I have a struct like struct MyStruct { int a; int b; int c: bool d; bool e; }
4
6438
by: blueblueblue2005 | last post by:
hi, I am reading the description of memcmp and strcmp, it seems there is no big difference between these two functions. except that memcmp takes void pointer parameters. so why string.h has these two functions doing the same thing?
6
3941
by: Sidney Cadot | last post by:
Hi all, Just browsing through my newly-acquired C99 spec, I was reading on the memcmp() function (7.21.4.1). It has a rather peculiar wording: int memcmp(const void *s1, const void *s2, size_t n); 1. The memcmp function compares the first n characters of the object pointed to by s1 to the first n characters of the object pointed to by s2.
2
8116
by: Mads Jacobsen | last post by:
Hi, Does anyone know the c#-function of c++'s memcmp()? Regards, Mads
7
12770
by: Alex Stark | last post by:
Hi, I'm new to c# an missing functions like memcmp and memcpy from C. Is there something similar ? cu Alex
4
14382
by: Preets | last post by:
Hi, Can anybody please tell me the difference between memcmp() and strncmp() functions ?
4
14352
by: system55 | last post by:
which of the 2 commands are applicable in comparing an array of unsigned chars? if(strcmp(aAbsCylNumHigh, bAbsCylNumHigh)<=0 && strcmp(aAbsCylNumLow,bAbsCylNumLow)<=0 && strcmp(aSecNum,.bSecNum)<0 ) or if(memcmp(aAbsCylNumHigh, bAbsCylNumHigh,2)<=0 && memcmp(aAbsCylNumLow,bAbsCylNumLow,2)<=0 && memcmp(aSecNum,.bSecNum,2)<0 )
0
9734
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9607
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
10408
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10137
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7673
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6895
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5561
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3874
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3026
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.