|
Hmmm. Guess I'm stupid. I'm not "constructing" the slice at all. I just assumed (incorrectly) that allocating the memory and setting a pointer to the front was enough.
Of course, I now realize that the vtable never gets setup, especially since I memset the allocated block to 0s. That's my crash problem.
The solution is to "construct" the objects in the block of memory, but I'm not sure I know how to do that, and I can't see how the new ((void *) pBlock) CDataSlice() would do it.
Would I use it ignoring the return?
for(i = 0; i < m_nBlockSize; i++) {
new ((void *) &pBlock[i * sizeof(CDataSlice)]) CDataSlice;
}
Guess not. Doesn't compile. I need some way of telling the compiler to construct the CDataSlice in the pre-allocated memory.
Any clues as to how to do that?
J
|
|
|
|
|
Jamie Hale wrote:
Guess not. Doesn't compile. I need some way of telling the compiler to construct the CDataSlice in the pre-allocated memory.
Any clues as to how to do that?
Yep - use a placement new. Look at the CSimpleArray class for an example.
|
|
|
|
|
Ok, CSimpleArray is a damn hard class to find. MSDN mentions it, and uses it in several examples, but fails to define it. Had to find an article by Grimes which makes me think it's probably all over my ATL books...
Anyways, I found that it uses an operator new overload with the second argument. I've also found a few other examples of it's use - the placement one. Unfortunately, I can't for the life of me get it to work in my code.
You can follow along in the thread below if you haven't got bored yet.
J
|
|
|
|
|
Guess not. Doesn't compile.
It should compile . Try putting extra parentheses everywhere:
new ((void *) (&pBlock[i * sizeof(CDataSlice)])) CDataSlice();
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
It does not compile. It's complaining about an ( and I've been over it a dozen times. It's almost as if it doesn't like this whole placement type allocation...
But if I understand correctly, new (something) class; translates into class::operator new(size, something); doesn't it? I haven't defined that override in the class, but a few other articles I've read seem to imply that a simple implementation of it gets built for you.
inline void * operator new(size_t, void *p) {
return p;
}
Mind you, this gives me odd compile errors when I add it...
I'm at a loss. I can appreciate what you're suggesting, and it looks like that's exactly what I need, but the damn thing don't work.
Any other suggestions? Any links to reasonable documentation on the placement-new would help too! MSDN is seriously lacking here.
Thanks so much for your time.
J
|
|
|
|
|
Excuse my stubbornness, but it's got to work. Maybe the compiler is getting confused... Would you mind trying this piece of code instead?
void * pv=(void *)&pBlock[i * sizeof(CDataSlice)];
CDataSlice * ps=new (pv) CDataSlice();
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Not your stubbornness... my compiler's (VC6.0 with the latest SP).
I copied that code verbatim, and it yaks on the second line saying "syntax error : identifier 'pv'"
It's almost like my compiler isn't set up to understand that?
J
|
|
|
|
|
Hmmm, just found that you're supposed to #include <new>, but adding it didn't change anything. It must get included through one of the other STL headers?
J
|
|
|
|
|
I think I got it. Does this article ring a bell for you? Seems MFC can interfere with placement new.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
That's it exactly. I can't imagine how long it took you to track that down, but thanks a ton.
I should have seen that. At one point in time, I was getting error C2061: syntax error : identifier 'THIS_FILE' where I defined my operator new. And that's because of MFC's debug memory manager. As soon as I commented the little boilerplate #ifdef blurb, it works fine.
Thanks so much for your time. I sure hope the block-allocation strategy actually helps performance!! If not, at least I learned about the whole placement-new thingy.
J
|
|
|
|
|
'scuse me butting in again, but I think you _do_ need the override.
Here's a quick link from google:
http://www.glenmccl.com/tip_025.htm
hmmm...
Actually, bad example - doesn't explain the need for explicit calls to the dtor for cleanup.
Got a copy of Stroustrup handy? That will explain it. Look for placement in the index - should show up under a Special Member Funtions section or some such...
|
|
|
|
|
No worries - I appreciate ALL input. I'm really stumped here.
I added the override, but it doesn't seem to help.
inline void *operator new(size_t, void *p) {return p;}
I don't want to do anything with it. The memory is already allocated - I just need the vtable setup for me and the default constructor called.
J
|
|
|
|
|
Almost there... I haven't quite got it conceptually (which makes it worth hacking on, I guess) but this _seems_ to work.
Just some details of the delete declaration to argue with the compiler about... there are some special rules for delete at the class level. BTW the new could be global as well...
Not sure if the vtable pointer is included in the size - tracking p in the new op shows 16?
Facinating stuff...
#include "windows.h"
#include <iostream.h>
#include <stdio.h>
class foo {
public:
foo(){}
~foo(){
cout << "destroying " << i << endl;
}
foo(int n) : i(n){
cout << "constructing " << i << endl;
};
void* operator new (size_t sz, void* p) {
return p;
}
<code>
private:
int i, j, k, l;
};
int main(int argc, char* argv[])
{
HANDLE hHeap = GetProcessHeap();
if(hHeap) {
void * vp = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 20 * sizeof(foo));
foo * fooPs[20];
for (int i = 0; i < 20; ++i) {
fooPs[i] = new ((foo*)vp+i)foo(i);
}
for ( i = 0; i < 20; ++i ) {
fooPs[i]->foo::~foo();
}
HeapFree(hHeap, 0, vp);
}
int x;
cin >> x;
return 0;
}
|
|
|
|
|
Yeah, I built a tiny little test program and it seemed to work fine. I'm convinced that placement-new exists and works.
There would be no vtable in the class you gave. If you had derived your class from another with virtual members, it would have been 4 bytes bigger.
class V {
public:
V() {}
~V() {}
virtual void wank() = 0;
};
class B {
public:
B() {}
~B() {}
void wank() {}
};
class D1 : public V {
int i,j,k,l;
public:
D1() {}
~D1() {}
void wank() {}
};
class D2 : public B {
int i,j,k,l;
public:
D2() {}
~D2() {}
void wank() {}
};
ASSERT(sizeof(D1) == 20);
ASSERT(sizeof(D2) == 16);
Anyways, Joaquín has hit on it. MFC's DEBUG memory management interferes. I'll post the details as a reply to his post above...
Thanks for your input.
J
|
|
|
|
|
Cool! Here's another take on it:
http://www.michaelmoser.org/memory.htm
might make the class more 'portable'.
A search on Google for 'placement new MFC' turns up lots of stuff. Looks like the relations between crtdbg, MFCs allocation routines, heaps etc. would make for a good article.
I'd give it a try, but I seem to have deleted everything I new...
|
|
|
|
|
how do you remove records that are marked for deletion.
i have tried flushResultSet but that does nothing. my odbc source is execlusive.
I can not find any function in the recordset class that can do this simple fuction. does it exist or do i have to build my own?
|
|
|
|
|
Change the type of your cursel type to dynamic or dynaset,maybe it works
Mazy
You can find a solution (even a foolish one) for all problems (even big ones)
|
|
|
|
|
if i use dynamic i get
dynamic cursors not supported by odbc driver
if i use dynaset i get
odbc driver does not support dynamic.
I seem to only be able to use snapshot.
does this mean i am out of luck?
I am using a VFP database if that helps.
|
|
|
|
|
What are you talking about Of course ODBC support dynamic and dynaset You can check MSDN
Do you use MFC?
Mazy
You can find a solution (even a foolish one) for all problems (even big ones)
|
|
|
|
|
i do not thing the messages reflect that odbc does not support dynamic or dynaset, but the odbc driver for vfp tables.
|
|
|
|
|
I don't know about vfp but it is so strange and very foolish for vfp that doesn't support them ,(oh,don't forget you have to define
your curser type before you open database.)
If you are sure about vfp why don't you change your database to access or SQLServer?with SQLServer you can import your database to access or SQLServer or any kind of database you want easily.(or you can also use ADO instead of ODBC)
I'm curios about this strange subject,if you find it out I'd be so pleased if you send message to this discussion board or send me email
Mazy
You can find a solution (even a foolish one) for all problems (even big ones)
|
|
|
|
|
I have two or more iterators that I get from find in multi-maps that I want to
- find the common items from OR
- merge
depending on user input.
What is the most efficient way of doing this?
OR
Should I store the items in a container in a map for each key and use the container for the purpose? If so, then what would be the ideal container and what is then the efficient way of finding common elements or merging.
The items can be in any order. The sort order is not important.
Thomas
modified 29-Aug-18 21:01pm.
|
|
|
|
|
I ran into this issue while working on a project :- it appears that VC6.0 compiler does not know how to generate the implicit copy constructor when a class has a data member that has more than 1 copy constructor declared. Not sure if this is a known VC6.0 (with SP3) bug.
Here’s example that demonstrates the problem :-
#include <iostream>
class A
{
public:
A() { std::cout << "A constructor..." << std::endl; }
virtual ~A() { std::cout << "~A destructor..." << std::endl; }
A(const volatile A& a) { std::cout << "A const volatile& copy constructor..." << std::endl; }
A(const A& a) { std::cout << "A const& copy constructor..." << std::endl; }
};
class B
{
public:
B() { std::cout << "B constructor..." << std::endl; }
virtual ~B() { std::cout << "~B destructor..." << std::endl; }
private:
A a_;
};
class C
{
public:
C() { std::cout << "C constructor..." << std::endl; }
virtual ~C() { std::cout << "~C destructor..." << std::endl; }
const volatile A& getA() { return a_; }
private:
A a_;
};
int main(int argc, char* argv[], char* envp[])
{
B b1;
B b2(b1);
C c1;
A a = c1.getA();
return 0;
}
Compiling this results in “C:\Projects\CopyBug\CopyBug.cpp(46) : error C2558: class 'B' : no copy constructor available”. This issue came about while working on class C which returns a const volatile reference to A & this necessitated adding a new copy constructor to A. Unfortunately, this broke B. Originally, I thought the VC6 compiler did not distinguish between const & volatile modifiers & perhaps this led to the problem. However, it turns out that the compiler is able to invoke the correct copy constructor as illustrated by a2, a4, a6 & a8 objects.
I then removed class C & its related code completely & tried to compile - still the same error. It appears that as soon as the second copy constructor is added to A’s declaration, the compiler fails to generate an implicit copy constructor for B. As long as there is only one copy constructor declared in A (doesn’t matter which one!), B’s implicit copy constructor gets generated properly.
Is this a known bug with VC6(SP3)? Any insights would be appreciated. Thanks.
Chen Venkataraman
|
|
|
|
|
It seems a bug to me --to the best of my knowledge, the compiler should construct automatically copy ctors with signatures B(const volatile B&) and B(const B&) .
Anyway, these issues are usually very subtle, and the interpretation of standard is a very hard task. I suggest you post this question to newsgroup comp.lang.c++.moderated. Put more emphasis on the behavior of the standard with respect to multiple copy ctors, cause the newsgroup moderators tend to ban posts relating to specific compilers.
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Anyone know how retrieve the path of an .ini file of an application?
GetProfileString retrieve only the ini file name, I would the path!
Grazie!
|
|
|
|