0

I'm using MFC C++ for my Windows Application, where I need to persist (not in a Database) some data using CMapPtrToPtr. The key is a pointer to a structure (let's call it SIGNAL_DATA* pSignal) and the value is a double array.

The problem is, when I read the value again, it is giving me a garbage/undefined value (not the value I stored).

Sample Code:

In the header file:

CMapPtrToPtr prevZoomValsMap;
double zoomPreVals[2];

In the implementation class:

void funktion1()
{

    if(ersteSchleife == FALSE) //first time, it is false
    {
        SIGNAL_DATA* pSelectedSignal; //properly initialised. verified in debug mode
        zoomPreVals[0]  = zoomMinSkal; //valid double values. verified in debug mode
        zoomPreVals[1]  = zoomMaxSkal;

        prevZoomVals.SetAt((void*) pSelectedSignal, (void*) zoomPreVals);
        ersteSchleife = TRUE;
    }
    else
    {
        funktion2();
    }
}

In another function, when I read the value as below, I'm getting garbage values.

void funktion2()
{
     void *zoomValuesTemp_;
     prevZoomValsMap.Lookup((void*) sigTemp, zoomValuesTemp_);
     double *zoomValuesTemp = (double*)zoomValuesTemp_;

     if(zoomValuesTemp == NULL) //verified in debug mode. never becomes NULL.
     {
          int aRTD = 10; //dummy assignment. 
     }

     double aValue = zoomValuesTemp[0] ; //Access Violation
}
m_drinks_coffee
  • 436
  • 8
  • 24
  • 3
    It looks like you're storing pointers to stack-allocated data into that map. Once the function returns, accessing data allocated on that stack frame is undefined behavior, as usual. – Frédéric Hamidi May 05 '14 at 07:13
  • I don't know what exactly you mean. But, I am passing the key (pointer: sigTemp) as a parameter for the other function. – m_drinks_coffee May 05 '14 at 07:18
  • You should read [Can a local variable's memory be accessed outside its scope?](http://stackoverflow.com/q/6441218/464709) It will put you on the right track. – Frédéric Hamidi May 05 '14 at 07:21
  • I don't understand, how the above provided links relates to my original problem. But, I read and understood it. – m_drinks_coffee May 05 '14 at 07:29
  • @javafan: How do you persist the data? Are you using the inherited CObject::Serialize function or the CDumpContext insertion operator (<<)? These should work. If you write your own function you'll have a lot more work for doing it right. – Werner Henze May 05 '14 at 07:37
  • persist in a sense, till the application is closed. then, i could discard the map. when I use CMapStringToPtr then there is no problem. The problem arises only when I use CMapPtrToPtr. – m_drinks_coffee May 05 '14 at 08:52

1 Answers1

0

Assuming that the code you provide is running in a function, we get

void store_it(SIGNAL_DATA* pSelectedSignal)
{
    double zoomPreVals[2]  = {zoomMinSkal, zoomMaxSkal}; //also, initialised.
    prevZoomVals.SetAt((void*) pSelectedSignal, (void*) zoomPreVals);
}

If this is what you have, then you are storing the address of a local variable (zoomPreVals) in the map. Since zoomPreVals is destroyed at the end of the function, the pointer to zoomPreVals becomes invalid. You cannot use this pointer anymore.

You must make sure that the pointer stays valid, so you can for example allocate a new structure with new and store the pointer in the map - don't forget to free the data later.

You might also consider using CMap<SIGNAL_DATA*, SIGNAL_DATA*, MYDATA, MYDATA&> and store objects instead of pointers as map values.

You might also consider using STL classes like map and unique_ptr.

Your retrieval code is not correct. You should not cast to match the function parameters, but pass the right parameters.

void *zoomValuesTemp_;
prevZoomVals.Lookup((void*) sigTemp, zoomValuesTemp_);
double *zoomValuesTemp = (double*)zoomValuesTemp_;
Werner Henze
  • 16,404
  • 12
  • 44
  • 69
  • I tried something like this. But, still the problem exists. `double* zoomPreVals; zoomPreVals = new double[2]; zoomPreVals[0] = zoomMinSkal; zoomPreVals[1] = zoomMaxSkal; prevZoomVals.SetAt(pSelectedSignal, (void*) zoomPreVals);` – m_drinks_coffee May 05 '14 at 11:16
  • @javafan: I updated my answer, your retrieval code was not right. – Werner Henze May 05 '14 at 13:17
  • Compiler Error: "error C2664: 'CMapPtrToPtr::Lookup': Konvertierung des Parameters 2 von 'double *' in 'void *&' nicht möglich" Translation in English: "Conversion of the Parameter 2 from 'double *' to 'void *&' not possible" – m_drinks_coffee May 12 '14 at 07:17
  • @javafan: I fixed that one. – Werner Henze May 12 '14 at 08:37
  • unfortunately, still doesn't work! when I read the values of zoomValuesTemp like this, `double aTempVal = zoomValuesTemp[0];` I'm getting Access Violation (Zugriffverletzung) Error in my Code. – m_drinks_coffee May 12 '14 at 09:22
  • @javafan Did you change the code to SetAt with a zoomPreVals that has not been allocated on the stack but on the heap (with new)? Please update your question with your latest implementation (or add that to the question). – Werner Henze May 12 '14 at 09:25
  • Just edited the code in the question part. I hope it looks understandable. If not, please reply back. – m_drinks_coffee May 12 '14 at 09:44
  • @javafan: Read my answer and implement it as I said, then it works. You have changed your code from SetAt(...,&localVariable) to SetAt(...,globalVariable). Now the pointer stored in the map stays valid, but for every call to funktion1 you set the global variable and put it's address into the map. So every map entry has the same pointer to the one global variable. And your one global variable is overwritten each time you call funktion1 with ersteSchleife==TRUE. – Werner Henze May 12 '14 at 10:49
  • Yes, you are right. How do you think, I should code (the approach), where I need to make sure the pointer stays valid throughout the lifecycle of application (until it is closed), without using global variable from the header file? thanks in advance. – m_drinks_coffee May 12 '14 at 11:52
  • @javafan Read my answer, you will find the answer to your latest comment/question there. EOD. – Werner Henze May 12 '14 at 11:59