|
I think markup ate his header.
There are several cases where this type of allocation is of great help. E.g. when reading or writing a known binary representation of some object. I do this quite a lot, not allocating ints, but rather do it on a byte level. Your suggestion of allocating the array and assign it to A->Iarray will simply not work in those cases, since you need a consecutive chunk of memory too work with. Properly wrapped in classes, this means you can memory map a file, and use pointers straight into the data. The typical struct holds a count accompanying the array(s).
struct Point
{
double x, y;
};
struct Polyline
{
__int32 pointCount;
Point points[2];
};
I think dialog templates are handled like this too.
As you point out, the delete has to be done on the byte array rather than on the mapped struct type.
|
|
|
|
|
I understand your words, but I fail to see under which circumstances such a construct would be needed, and in what way my suggestion wouldn't work. The only difference would be the need for an additional 4 (or 8) bytes for the pointer variable. In return, you'll get a struct that actually does what the definition implies rather than one that will inexplicably fail on standard assignments.
[edit]
P.S.: just thought of an example that would indeed benefit from such a construct: memory allocation functions. You'd allocate a consecutive chunk of memory big enough to not only hold the array of data as requested, but also additional info (such as block size or debug info), then return the starting address of the array. Upon deletion, thanks to the consecutive block, you can manipulate the pointer to the array to access that additional information again.
In this case, the consecutive allocation serves as a means to store hidden information and later access it with no additional info required beyond the address of the user data.
Not something you couldn't also do with C++ constructs such as delegates, but that is what to my knowledge the debug implementation of new and delete do.
[/edit]
|
|
|
|
|
One example could be if you use CreateDialogIndirect, which accepts a CDLGTEMPLATEEX[^]* as one of its arguments. The size of this 'struct' cannot always be determined at compile time, since you could change a string value dynamically before creating the dialog.
The title character data is expected to be found at an offset from the start of the struct, and it's supposed to be zero-terminated, with the pointsize member following directly after (on a word boundary I suppose).
[edit about your edit]
That would indeed be one usage. Not one that I have tried, but a simple way to do buffer overflow checks I suppose, where you could put signature data around your memory block.
[/edit about your edit]
[edit]
Stefan63 wrote: not only hold the array of data as requested, but also additional info
This, of course, is the key issue. Maybe I wasn't very clear about that.
[/edit]
home
modified on Wednesday, February 16, 2011 4:47 AM
|
|
|
|
|
I'm not a compiler but since at compile time the compiler doesn't know the string contained in title , it would translate every reference to pointsize into an offset to the start of the struct, using titleLen as length for title . At runtime, the end of title might come long before the end of the reserved string, but the remaining bytes would just be unused.
Similarly, any assignment of this struct would copy the memory block using the size determined by titleLen and stringLen (which I take to be constants that are defined elsewhere).
Assuming your interpretation would be correct, and one of these structs would use a title of 4 characters length, whereas another was defined with a title of 20 characters length, then the second gets assigned to the first. Not only would you write past the boundaries of the memory block allocated for the first struct, you'd also invalidate any pointers to elements of the first struct that point to elements past title !
|
|
|
|
|
I know. There are ways to get around this. The easiest case is if the dynamic part is at the end of the struct. If not, you can split the struct into two parts, so each ends with a dynamically sized data, to match the binary signature. It's rather simple really as long as you know how to calculate the offsets properly.
Edit:
titleLen and stringLen are NOT constants, which is the whole point here.
home
modified on Wednesday, February 16, 2011 5:21 AM
|
|
|
|
|
I will try to explain this in a different way. Suppose you call a black box API with returns a pointer to a chunk of memory. According to the specifications, the first four bytes are an integer containing a version number of the data. After that there is a four byte unsigned integer giving how many samples you will get, followed by that many eight byte double float sample values.
In code that might look like:
void *data = GetSamples();
int version = * (int*) data;
unsigned int sampleCount = * (unsigned int*) (( (char*) data ) + sizeof(int))
double *samples = (double*) (( (char*) data ) + sizeof(int) + sizeof(unsigned int))
This will extract the variables needed, and they are now ready to be used. The way they are found is rather error prone.
A better way of doing this would be to map a known struct over the data with the same binary representation
struct Samples
{
int version;
unsigned int sampleCount;
double samples[];
};
void *data = GetSamples();
Samples *samples = (Samples*) data;
Now I can use samples as if it was a pointer to Samples . The good thing here is that the compiler will help me calculate the offsets for each known part of the binary data. This is the reverse of what I described in my earlier post.
Now assume there is another API which accepts such a set of binary data for processing, ProcessSamples(void* data); How would you construct the data if you only had the specification to it, and the data you had access to was in another format?
struct Samples
{
int version;
unsigned int sampleCount;
double samples[];
};
size_t dataSizeNeeded = sizeof(int) + sizeof(unsigned int) + sizeof(double) * mySampleCount;
char *bytes = new char[dataSizeNeeded]; Samples *samples = (Samples*) bytes;
samples->version = 1;
samples->sampleCount = mySampleCount;
for (size_t i = 0; i < mySampleCount; ++i)
{
samples->samples[i] = ...;
}
ProcessSamples(samples);
delete [] bytes;
The compiler will again help with the offsets, even though we're dealing with a 'dynamically sized struct'.
N.B. I intensionally left out important info on struct member alignment, Microsoft extensions to the C++ language, size of data types, data hiding, how to handle multiple dynamically sized members in the same 'struct', and the sample is not from the real world.
|
|
|
|
|
Thanks for your effort but I'm afraid it goes wasted. I totally understood what this is about, As I pointed out before, it's like what new and delete do, only that they're not bothering to define a struct. And, btw., CDLGTEMPLATEEX is probably worse than that, as not only is there no actual definition of that 'struct', some of it's members may be missing entirely! That's what confused me.
I still fail to see why it's better to hack a struct than just use pointers for the dynamic parts. That kind of coding was bad style in times before C++, and it's even worse nowadays. I'd put it on par with using goto , but that might do goto injustice. What we're talking about here is self-modifying data, and I don't see how that is any better than self-modifying code.
The only justification I can think of is some low level code that is really, and I mean REALLY keen to save the extra memory required for the pointer(s). For coding it makes no difference at all. For memory usage, you just need one additional pointer for the dynamically sized part. For efficiency, you only add one level of indirection for resolving access to elements of the dynamic part. In return you get clear data structures that describe what is actually there, remove the need to unsafe type-casting, and get code that is much more readable and maintainable.
IMHO, that MS is still using such techniques is an abomination. And it is no reason to use such techniques yourself.
|
|
|
|
|
It's not about saving the space required by a pointer. It's about the black box. If one could design it all from the beginning, this would never have been discussed. The problem is that one can't change the requirements a black box has. You can't change how Microsoft expects to receive the data for a binary dialog template. You can't redesign the structure.
Why would you want to deal with pointer arithmetics if the compiler can do it for you? Remember that this is about well defined binary representations only. Not data that will change depending on processor architecture or operating system version.
|
|
|
|
|
Niklas Lindquist wrote: If one could design it all from the beginning, this would never have been discussed. My point exactly.
I am aware that you have to deal with it if you want to access MS's interfaces, and I understand why you would provide pseudo-definitions for the structures being used in that case.
But since the OP didn't do that there was no reason to use such a construct in the first place. Hence I suggested using a pointer instead.
|
|
|
|
|
Ok. In retrospect, I was reading more into the OP question than was really there. To me it looked as if it was a binary layout going on, which he later indicated there wasn't.
|
|
|
|
|
No worries. I did ask what such a construct would be good for, so I shouldn't have been surprised to receive an answer, even if it was unrelated to the original problem.
|
|
|
|
|
It works, thanks a million. I knew it was something small (i.e. boneheaded) that I was doing wrong. I guess blinding following some articles on the MSDN can lead you into trouble (since they never give you the big-picture view).
|
|
|
|
|
Hi everybody,I used vc 2008 sp1 and created a dialog app.I used
CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
in CAppEx::InitInstance(),but there were nothing happaned.I wonder thether the dialog app couldn't use CMFCVisualManagerOffice2007 .
Thanx.
|
|
|
|
|
stephen_young wrote: in CAppEx::InitInstance(),but there were nothing happaned.I
I do not think that these styles can be used with dialog apps. To verify, create an SDI app.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
Thanx David.Yes the SDI app is OK!!
|
|
|
|
|
Hi!
Is it possible to MultiLanguage Support Facility(e.g English,Chinese and Korean) with VC++? Can any body point me the direction
|
|
|
|
|
Your VC++ program can support multiple languages if you use Unicode versions of API calls. You can build your project with Unicode settings.
You can check out the book "Advanced Windows" by Jeffrey Richter.
|
|
|
|
|
See the eMule source code.
It supports these threee language.
|
|
|
|
|
Yes It is possible.
1) You have to install supplement language support for other languages. You can check it with Control Panel -> Regional and Language option.
2) Set your project as Unicode not ANSI.
I believe in LOVE AT FIRST SIGHT...
Bcoz I have loved my Mother...
even since I opened my eyes...(ICAN)
|
|
|
|
|
In addition to above answer you can also go there[^] to read thread about same toppic.
|
|
|
|
|
Hi!
I've to implement Remember me facility. i.e My application has a log in Form. In this
log in Form, there are two text boxes(one for entering user name and another one for entering
Pass Word), a check Box(called "Remember Me") and a Button called Log in. If the check box is
checked,When we run the exe at the next time, these two text boxes should be filled by the already entered user name and Password. How to do this in C++?
|
|
|
|
|
You should make persistent your application settings (for instance writing them inside the registry). make sure to crypt the password, then.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
CPallini wrote: for instance writing them inside the registry
Can u elaborate on this?
|
|
|
|
|
You may have a look at one of the many articles about the registry here at CodeProject, see, for instance, Newcomer's A Registry Class[^].
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Hi,
I have a specific problem:
I need to draw a text like "HomeSweet Home" but it should wordwrap and after wrapping It should be displayed as
"HomeSweet
Home"
how can I do that?
|
|
|
|