|
What version of SQL was that?
What was the count of unions that caused this?
Thank you.
|
|
|
|
|
Which means "Stop doing this to us in here!"
Just for more gig-gles, sent it over and over and see is the "rare event" message changes.
|
|
|
|
|
struct Record
{
unsigned short Length;
unsigned long ObjectId;
LevelType Level;
unsigned long SendBlock;
struct
{
unsigned long SendBlock : 31;
unsigned long SendBlockMarker : 1;
};
__time32_t SendTime;
struct
{
Type SendType : 16;
unsigned SendVersion : 16;
};
unsigned long SendNumber;
union
{
struct
{
char Message[1];
} Version0;
struct
{
__int64 EventTime;
char Message[1];
} Version1;
};
};
:face-palm:
Software Zen: delete this;
|
|
|
|
|
What's wrong isn't obvious to me.
It looks like SendVersion tells you which union to look at.
If sent interprocessor, it will pack differently on 32-bit and 64-bit CPUs, ignoring endianism problems. The fact that there's a version number suggests that this could be the case.
|
|
|
|
|
There's a #pragma pack around the declaration.
I'll give you a couple hints: it's before SendVersion . This compiles successfully under VS2008 (don't ask), and I've not tried compiling it under VS2019. It should trigger a compile error.
Software Zen: delete this;
|
|
|
|
|
The two SendBlock fields? Maybe VS2008 accepted it because the second one was inside an unnamed struct .
|
|
|
|
|
BINGO!
Software Zen: delete this;
|
|
|
|
|
In short: everything!
Where should I start? The unsigned long of 1 bit? The SendBlock doubly defined? The version union with members in wrong order? The complete lack of comments?
I hope they pay you well to put up with this pile of manure
Mircea
|
|
|
|
|
The union with members in the wrong order is likely correct. In Version1 , EventTime was added to timestamp messages. It's followed by the Message contents, which are at the end of the message and claim to be of type char[1] , but which will actually be indexed from 0 to Length - 1 .
Writing types for message byte buckets is fun, especially when you add protocol version control!
|
|
|
|
|
Greg Utas wrote: type char[1], but which will actually be indexed from 0 to Length - 1 My instincts are telling me that it's a placeholder for variable-length data.
With MSVC you cannot use a zero-length array unless the following conditions are true:
1.) It must be the last field in the union or struct.
2.) Option /Za must be enabled.
3.) Option /permissive- must be unset/disabled
Or you can just do char[1]
|
|
|
|
|
And then you receive a zero-length message (header only), and someone does a memset using the size of this type, trampling over the char[1] that isn't there.
|
|
|
|
|
Heh,
I'm not advocating the technique, I am just pointing out what I see in the struct.
|
|
|
|
|
Randor wrote: My instincts are telling me that it's a placeholder for variable-length data. Exactly right. The struct is actually header for the information content which follows.
Software Zen: delete this;
|
|
|
|
|
Mircea Neacsu wrote: The unsigned long of 1 bit? An unsigned value 1 bit in width is slightly more useful than a signed value 1 bit in width, if you think about it.Mircea Neacsu wrote: The SendBlock doubly defined? That's the error I was referring to. IMO the compiler should issue an error, since the identifier SendBlock is ambiguous when referencing fields in the struct . This code is compiled using VS2008 which does not issue a diagnostic.Mircea Neacsu wrote: The version union with members in wrong order? They're in the correct order. The Message value must be at the end of the structure, since it is a placeholder for the beginning of the variable-length data that's included in the message.Mircea Neacsu wrote: The complete lack of comments? This is a code fragment, extracted from a header file that provides more context.Mircea Neacsu wrote: hope they pay you well to put up with this pile of manure They do pay me well, in the coin that really matters: appreciation. I've worked for the same company for over 30 years, and have survived numerous "workforce reduction" actions during the last period of financial instability.
As to its fecal quality, I didn't create this originally but I have maintained it over the last 20 years. This 'weird & wonderful' came up during some refactoring I'm doing while adding a new feature.
Software Zen: delete this;
|
|
|
|
|
Gary R. Wheeler wrote: An unsigned value 1 bit in width is slightly more useful than a signed value 1 bit in width, if you think about it.
Yes, but long...
Gary R. Wheeler wrote: They do pay me well, in the coin that really matters: appreciation. I've worked for the same company for over 30 years,
I understand. I've worked for the same company for 22 years and enjoyed every minute of it... well, at least most minutes
Mircea
|
|
|
|
|
Mircea Neacsu wrote: Yes, but long In this environment, 32 bits. The original value was an unsigned long .
Software Zen: delete this;
|
|
|
|
|
Gary R. Wheeler wrote: struct
{
Type SendType : 16;
unsigned SendVersion : 16;
};
This appears to be a bit field shared between two different data types. I am assuming Type is an enumeration type which is a signed integer. The other 16 bits are unsigned.
|
|
|
|
|
As someone else mentioned, this is part of a message protocol definition. This struct was originally a single, unsigned 32-bit value called SendType which was indeed an enumeration. We've occasionally had the need to add features without removing the ability to handle older versions. This was one solution to the problem. Messages in the original format (which don't know about SendVersion ) therefore have an appropriate SendType with a SendVersion of zero (0).
Software Zen: delete this;
|
|
|
|
|
This smells like nifty code. Nifty code is brittle. If it's difficult to understand a struct, you're doing it wrong.
That said, you have existing code and must maintain compatibility so...
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
charlieg wrote: This smells like nifty code. Nifty code is brittle. If it's difficult to understand a struct, you're doing it wrong. I heartily agree. This struct defines the message format used by our in-house diagnostic tool. Our applications are multi-machine, multi-process, and multithreaded. Each process includes a small TCP/IP socket-based server that communicates with a client application. Code in the process uses the server like printf on steroids. The client in turn handles as many server connections as needed, displaying and recording them. The servers and this tool has been essential for both development and problem diagnosis in the field for us for the last 20 years. It's been maintained and refactored numerous times. We have systems in the field that are over 10 years old, so backward compatibility is an absolute requirement.
The good news is the code around this definition abstracts away the awkwardness of this definition.
Software Zen: delete this;
|
|
|
|
|
And the structure is just evil completely through...
If you have to stare at something like this - here's your sign.
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
Message would cause a name clash in the 2 struts.
So MessageOld, MessageNew
|
|
|
|
|
In a standup today, discussing a particular code repository. Sometime in the past, someone created a backup of one of the projects, then worked on the original project. Afterwards they checked everything back into repository, including the backup.
So my team is now working on this, and the developer was wondering whether this backup needs to be updated. I commented that if this is just a backup and no longer being used, we should just delete it. Keeping in mind that if it is still needed, it still exists in the history of the git repo.
So of course a big discussion began, with the other developer arguing that we don't know why it is still there, maybe it's still needed, etc. The final decision was to take this one instance to the main IT manager to provide "guidance".
Whatever happened to developers taking responsibility and making informed decisions? We are supposed to be senior developers, and capable of making a decision without having to have a committee meeting, or passing the buck to senior management.
If I was that manager and was asked that question, I think I would be a bit pissed off and have some serious doubts about this team....
EDIT
I should have remembered, this is a large government agency. And there is a huge mentality of covering you b#?! and taking responsibility for anything. I guess that is what they have us contractors for....
|
|
|
|
|
Is it causing any trouble?
|
|
|
|
|
Yes and no. Personally I don't care that much one way or another. I just find that this is a lot of passing the buck, and a non-willingness to clean up things that are not needed (a bit of YAGNI I feel).
However we do have automated scans that look at the repos and see which might need work, such as updating libraries and. Net versions used. Keeping this in there just generates false positives that then have to be looked at. And these projects tend to be floated around various teams that may not be aware of what these duplicated projects are about.
I am of the mindset that if I am working on a project, and find unused code, it should be cleaned up. Just more technical debt to deal with.
|
|
|
|