|
That is not the problem. I don't even reference the pointer. I reference an element of the vector that has been destroyed. I could leave the delete on the vector and it would still print nonsense. The reference to the integer stored in the vector has become invalid. I have this problem because i need to implement a wrapper for a map on wich multiple threads can operate concurrently, inserting, reading and deleting. Now one thread could delete an element another thread is currently working on. Since the objects are managed by the map itself i cannot find out when that happened.
|
|
|
|
|
what do you mean by "print non-sense" ? what do you expect ?
[edit]
oh, my bad, i read your post incorrectly (i read that you were printing out the address in the testVector pointer).
AFAIK, a reference cannot be changed of address, so by clearing the vector, then deleting it, you invalidate the reference. the only way you have to know the reference may be invalid is not writing such code.
i don't think we can know otherwise
BTW, it seems that you need some synchronizing code around your vector... one should not read it until another thread finished to modify it, and such references being temporary shouldn't be stored
[/edit]
|
|
|
|
|
Synchronization is of course neccessary (bad seplling ?!), but i want to keep it minimal, since too much synchronization can make a multithreaded application almost sequential, this voiding the advantage of multithreading.
It is also correct that the reference should not be stored, but experience tells us, that users always do whatever it takes to crash a program, or the library in that case. So i try to keep my code bulletproof.
My approach now is to write a wrapper-class that behaves like a reference, but checks on every access weather the elemennt/vector actually still exists. I'm not sure though if that is the smartest way to do it, it seems like a waste of resources.
|
|
|
|
|
Mr.Brainley wrote: but i want to keep it minimal
don't keep it "minimal", keep it efficient. if you have too much synchronization, then there may have a design problem.
for your vector, the need of the mutex is pretty neat...
|
|
|
|
|
Mr.Brainley wrote: I reference an element of the vector that has been destroyed.
This would be impossible if you had assigned NULL to the pointer after deleting it.
It's a two-step process. Assign NULL to the pointer after deleting it, and check if the pointer is equal to NULL before referencing it.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
A try/catch around the dereference would do it, but it's cumbersome to have many of those throughout the app. In C++, it's your responsibility to not do that in the first place.
|
|
|
|
|
Michael Dunn wrote: A try/catch around the dereference would do it, but it's cumbersome to have many of those throughout the app. In C++, it's your responsibility to not do that in the first place.
I don't think it would (do it). This approach is dangerous. The memory manager could have reused the address that used to contain the vector 's contents after the vector has been destroyed. This technique can not be relied upon.
Steve
|
|
|
|
|
Mr.Brainley wrote: How can i detect that the reference has become invalid ?
You can not; a reference just refers to a memory block that is expected to contain data of a given type (the referenced data type). It is up to you, the programmer, to insure that the memory block is valid, as the language does not provide that for you.
If there is a chance that the memory block will become invalid without you knowing it, bad design, then you could try using one of Microsoft’s “IsBad…” functions to check the address referred to by the reference: IsBadWritePtr(&testRef,sizeof(int)) . This method, of course, may not work if some other piece of code has allocated that same memory block between the time you freed it and the time you checked the address pointer; which will lead to very hard to find bugs.
Another thing I would like to point out is that just adding another item to the ‘vector’ can cause your reference to become invalid if the ‘vector’ had to reallocate memory in order to expand the memory block size.
Basically, any reference, of the type you provided, should be temporary and only exist in local scope. It should not be ‘static’ or ‘global’, unless the memory it refers to is not released until the application exits.
INTP
"Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
|
|
|
|
|
The best solution would be not to get in this situation. There are other solutions however. For example you could construct a container based on a std::vector that uses something like Boost's Shared Container Iterator[^] and use iterators instread of usig ponters. Other smart pointer based techniques are also possible. A std::vector as it stands is not designed for this usage pattern (and doesn't pay the price that implementing it incurs).
Steve
|
|
|
|
|
Mr.Brainley wrote: How can i detect that the reference has become invalid ?
You can't.
BTW, vector objects are not meant to be created on the heap.
|
|
|
|
|
I'm porting an old app that was created in VC6 in C-code to VS2005 C++ code. This is an api app that hits a shared lib for interaction with the main app. As soon as I change from C to C++ and build, I have unresolved externals... change back and it builds fine... I've added the project dirs (include and lib), maybe missed something else?? Any ideas?
This seems to apply to functions from the shared lib, as well as other c-coded functions in the solution:
gen_geo.obj : error LNK2019: unresolved external symbol _rabs referenced in function _make_bbox
Thanks
|
|
|
|
|
Sometimes just stating a problem helps you fix it...
A good ole' extern "C" {} around the api #includes did the trick
Thanks for allowing me to waste your time
|
|
|
|
|
A stated problem with a good solution is never a waste of our time, in my opinion. If they have not already, then one of the guys who likes compiling solution faqs will include this.
Good work!
INTP
"Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra
|
|
|
|
|
Hello,
I have an OCX that works on the PC built with VS6.0. It registers correctly and can be used to write more C++ applications with it.
The OCX has been ported to Embedded platforms(PPC 2003 SE). It builds via eVC++ 4.2 with 0 Error(s) 0 Warning(s) for PocketPC 2003 SE for the processor I'm using. The "build" output-window says it registers correctly. I'd love to say it works; however, I can't prove it.
Both IDE's say it registered correctly.
Here's the problem:
I open the eVC project I'm going to be using this OCX with. I go to Project->Add to Project->Components and Controls and attempt to add control - my shiney new OCX. (I imagine that eVC desires the embedded OCX vs the PC OCX - though, admittedly, I've tried them both.)
Every time I try to add the control I get the following message:
"Failed to find desktop version of control in registry. Please verify that this control has been successfully registered on the desktop."
So, I ask, what am I doing wrong here?
|
|
|
|
|
~!^)&*(^!@#)&*^~
I found several problems.
First problem was PEBKAC. I was navigating to the build output directory of the ActiveX control and not the registered components directory one would find their registered controls in. But, why would I do that, you ask? Well, every time I navigated to the registered controls directory, it was empty. Which leads me to the second problem.
eVC defaults the developer to the 'Registered ActiveX controls' for the embedded development directory:
C:\Program Files\Microsoft eMbedded C++ 4.0\Common\EVC\Gallery\Registered ActiveX Controls
It *wants* the PC's! 'Registered ActiveX Controls' directory.
C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Gallery\Registered ActiveX Controls
Is it just me or is this counter-intuitive?
So, I navigate there. It too is empty....huh!?
Thirdly, eVC doesn't (or, isn't, on my PC) displaying the Visual Studio 'Registered ActiveX Controls' directory *unless* VS6 is open and is being 'fooled' into thinking someone is trying to 'add a Component or Control' for a VS6 project.
So, there you go. I'm totally disgusted.
|
|
|
|
|
Hi,
I'm new to C++ programming, and i'm having a problem passing pointer to array.
Here is the code:
typedef struct {
int i;} tpteste;
int test (tpteste * l)
{
l = new tpteste[4];
l[0].i = 99;
l[1].i = 98;
l[2].i = 97;
l[3].i = 96;
return 0;
}
int doNothing(void)
{
int j = 0;
tpteste * w;
j = test(w);
return 0;
}
When the "test" function returns, there's nothing in the pointer "w". It does not change it's value.
It may be a dummy question, but i'm having a bad time here with it...
Thanks in advance.
Renato Carvalho.
|
|
|
|
|
wrote: int test (tpteste * l)
{
You need to pass here pointer to pointer as argument. Your function should look like
int test (tpteste ** l)
{
*l = new tpteste[4];
l[0]->i = 99;
l[1]->i = 98;
l[2]->i = 97;
l[3]->i = 96;
(*l)[0].i = 99;
(*l)[1].i = 98;
(*l)[2].i = 97;
(*l)[3].i = 96;
return 0;
}
-- modified at 10:27 Wednesday 14th February, 2007
-- modified at 23:19 Wednesday 14th February, 2007
|
|
|
|
|
prasad_som wrote: *l[0].i = 99;
Not quite.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Result of trying to be fast in reply.
Anyway, OP's problem was addressed in my reply.
|
|
|
|
|
prasad_som wrote: Anyway, OP's problem was addressed in my reply.
Actually it wasn't. You'll notice that the first two assignments in test() "appear" to work, but the last two will fail miserably.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
I tried the changes, but it did not compile. Then i changed the assignments at function "test" to "l[X]->i = 99;" and it compiled.
But, in fact, when it runs, the 3ª instruction fails with an access violation.
The code now looks like this:
typedef struct {
int i;} tpteste;
int test (tpteste ** l)
{
*l = new tpteste[4];
l[0]->i = 99;
l[1]->i = 98;
l[2]->i = 97;
l[3]->i = 96;
return 0;
}
int doNothing(void)
{
int j = 0;
tpteste * w;
j = test(&w);
return 0;
}
|
|
|
|
|
Renato Carvalho wrote: But, in fact, when it runs, the 3ª instruction fails with an access violation.
Of course it will. That's what I was trying to "hint" to Prasad.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Agree. Again, it was wrong way of accessing array.
DavidCrow wrote: prasad_som wrote:
Anyway, OP's problem was addressed in my reply.
Actually it wasn't
You can see, OP's was facing problem due to passing pointer(by value ofcourse), and allocating memory for it inside function, which I corrected by sugggesting pointer to pointer(**) way. I was underlining that point. Modiefied original reply to run correctly.
|
|
|
|
|
That's the result:
int test (tpteste ** l)
{
*l = new tpteste[4]; //error C2228: left of '.i' must have class/struct/union type
*l[0].i = 99; //error C2228: left of '.i' must have class/struct/union type
*l[1].i = 98; //error C2228: left of '.i' must have class/struct/union type
*l[2].i = 97; //error C2228: left of '.i' must have class/struct/union type
*l[3].i = 96; //error C2228: left of '.i' must have class/struct/union type
return 0;
}
int doNothing(void)
{
int j = 0;
tpteste * w;
j = test(w); //error C2664: 'test' : cannot convert parameter 1 from 'tpteste *' to 'tpteste ** '
return 0;
}
In fact, it did not compile. But i will try to work on "pointer to pointer" solution. It's been a long time since i studied C at graduation, and i think a forgot some important points.
But thanks for answering.
|
|
|
|
|
Renato Carvalho wrote: j = test(w);
change with test(&w)
|
|
|
|