Solved

C++ vectors pairs and dynamic buffers

Posted on 2011-03-15
17
567 Views
Last Modified: 2012-05-11
I want to use vectors to store two variables, integers and data. My initial thought was to store the data as a paired vector sort of like:
typedef std::vector<pair <const UInt8_T *, int > >  MyVector;
MyVector myVector;

// store the data to the vector

// data that is passed into a function as
const UInt8_T* pBuff and int nLen

myVector.push_back(pair<const UInt8_T*, int(pBuff, nLen));

but I noticed when I read the data back using:
for (vector<pair <const UInt8_T *, intT > >::const_iterator  It = myVector.begin(); It != myVector.end(); It++)
{
     const UInt8_T * rtData = It->first;
     or
     const UInt8_T * rtData = (*It).first;
}

rtData does not match the data that is passed in via the push_back call.

I am assuming I need to do some kind of new or something to hold the data instead of just a pointer to the data for the data being passed in as 'buff' might be released at some time before the call to the for loop, I am just not sure how to do the 'new' with a vector of buf data. Also I was thinking maybe I have to do a class or structure like:
myStruct
{
   const UInt8_T * data,
   int nLength
}
but then I still would have to do some kind of new and delete for the memory.

I would like some examples and/or suggestions how to accomplish saving both items, the data in the buffer and the buffer length via a vector type.

Thanks
0
Comment
Question by:atomicgs12
  • 6
  • 6
  • 4
  • +1
17 Comments
 
LVL 32

Expert Comment

by:phoffric
ID: 35143906
>> myVector.push_back(pair<const UInt8_T*, int(pBuff, nLen));
not sure why you have two args for the int
maybe typos.. since there is the right >

>> // data that is passed into a function as
>> const UInt8_T* pBuff and int nLen
  What is your UInt8_T pointer pointing to. If it is pointing to a UInt8_T that is on the stack of this function, then when you return from the function, that stack location is likely to be overwritten, so your pointer's address may no longer have the value that was originally placed in it when you returned from the function.



0
 
LVL 32

Expert Comment

by:phoffric
ID: 35143909
Did you want to use make_pair ?
     http://www.cplusplus.com/reference/std/utility/make_pair/
Here is sample code from this link:
#include <iostream>
#include <utility>
using namespace std;

int main () {
  pair <int,int> one;
  pair <int,int> two;

  one = make_pair (10,20);
  two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>

  cout << "one: " << one.first << ", " << one.second << "\n";
  cout << "two: " << two.first << ", " << two.second << "\n";

  return 0;
}

Open in new window

0
 
LVL 32

Expert Comment

by:phoffric
ID: 35143921
If you post a short sample program that illustrates the problem using the pair approach, then I'll run it and point out the problem.
0
 

Author Comment

by:atomicgs12
ID: 35143944
Yes a typo should read:

myVector.push_back(pair<const UInt8_T*, int> (pBuffer, length));
" What is your UInt8_T pointer pointing to."  Is pointing to a data buffer, any hex values, e.g.  char data[] = "abcdef";
const UInt8_T* pBuff = data; something to that effect.
0
 

Author Comment

by:atomicgs12
ID: 35143956
"Did you want to use make_pair ?
     http://www.cplusplus.com/reference/std/utility/make_pair/
Here is sample code from this link:"

No I have to use a vector and the first item of the pair has to be a buffer that can take varying sizes of data. Int pairs are easy and plastered all over the net. But thanks for trying.
0
 
LVL 32

Expert Comment

by:phoffric
ID: 35144074
I don't know exactly what your problem is. I used some of your code in your OP and found no problem (also used make_pair as well as pair). I'll be back in 1-2 hours and will review your posted program.
0
 
LVL 32

Expert Comment

by:phoffric
ID: 35144350
If you are passing a vector into a function and doing the push_back there, then the arg should be passed in as a reference to a vector rather than as a vector; otherwise the changes you make to the local vector will not be seen by the caller.

>> I am assuming I need to do some kind of new or something to hold the data instead of just a pointer to the data for the data being passed in as 'buff' might be released at some time before the call to the for loop
    Now I see that you know that you cannot release the 'buff' and then use any pointers that are pointing to 'buff' or an element in 'buff'. So, it is then clear to you that if you wish to use a pointer rather than the value itself in the first of the pair, then somehow you need to have a valid memory location that you are pointing to. But this is true for any pointer, and not specific to using a pointer in vector.

0
 

Author Comment

by:atomicgs12
ID: 35144415
OK there is a lot of going back and forth with nothing really getting answered.

 If anyone knows vectors just so me how to use a vector like:
vector<pair <char *, int > >  MyVector;

where MyVector is global and can be called from any where in the program and char* is a buffer.
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 32

Expert Comment

by:phoffric
ID: 35144431
I thought you had a program that ran incorrectly. I was willing to help you to show you quickly the problem with your program. All of your code and including the corrected typo:
     myVector.push_back(pair<const UInt8_T*, int> (pBuffer, length));
works fine. You could use struct as you thought, but you don't have to. Your pair approach works fine. But I'll leave you now. I believe someone else will be able to assist you shortly.
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 35145099
Hi atomicgs12,

you should post some relevant parts of your code - especially interesting is where the pointer is initialized.

You say you have something like 'char data[] = "abcdef"' - so I guess you repeatedly add 'data' (maybe after modifying the string it points to).

This would mean you pass the same pointer but only change the value this pointer points to. As soon as the pointer 'data' gets out of scope the data where the mulitple stored pointer points to is invalid.

So, for every pair of pointer and int you want to insert you have to instantiate a new pointer i.e. using 'new' - and, whenever you remove an element from the vector you have to explicitely release the allocated memory using 'delete'.

If you need your vector to store strings you should think about using std::string (or even maybe a vector i.e. for storing a list of ints) instead of a 'char' pointer. If not and if you still think you need pointers you should think about using some kind of smart pointers (this may depend on which compiler/STL you use) which you still have to initialize but don't need to take care about releasing the memory.

ZOPPO
0
 
LVL 32

Accepted Solution

by:
sarabande earned 500 total points
ID: 35146678
if you store a pointer to a vector the vector only makes a copy of the pointer and not a copy of the data the pointer is pointing to.

that normally is bad design cause you need to allocate new storage for the pointer before storing it in the vector and must not use that storage again while the pointer is stored in the vector. whenever you erase or clear from vector you need to read the pointer before and delete it or you would get memory leaking.

you can avoid all that by not using pair but a vector<UInt8_T> which can hold an array of UINT8_T elements and has full copy semantics. that means if you store that vector into myVector you would get full copies of the elements and if you clear the myVector all memory gets freed.

  std::vector< std::vector<UInt8_T> >  myVector;

  std::vector< std::vector<UInt8_T> >::iterator i;
 
  for (i  = myVector.begin(); i != myVector.end(); ++i)
  {
        UInt8_T * data = &i->at(0);
        int len = (int) i->size();
        ...
  }


Sara
0
 

Author Comment

by:atomicgs12
ID: 35148339
sarabande: I think you on the right path. How would I store the data in std::vector< std::vector<UInt8_T> >  myVector; if the data was passed to me as say const UInt8_T* pBuf?

Thanks
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35148483
you would do

   std::vector<UInt8_T> v(&pBuf[0], &pBuf[len]);

that creates vector and fills it from pBuf[0] to pBuf[len-1].

Sara
 
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35148579
you also could do (to avoid multiple copies) :

  myVector.push_back(std::vector<UInt8_T>());  // adds empty vector
  // get a reference to the last vector inserted
  std::vector<UInt8_T> & vref = myVector.back();
  vref.insert(vref.begin(), &pBuf[0], &pBuf[len]);

Sara
0
 

Author Comment

by:atomicgs12
ID: 35149173
sarabande: Perfect
One last think, how would I make sure there is no memory leaks afte I'm finished with the vector? Would it be as simple as myVector.clear()?

Thanks
0
 
LVL 32

Expert Comment

by:sarabande
ID: 35149518
yes, each vector would delete all its objects.

note, that doesn't apply for the pBuf input. the pBuf is only used for reading the values and the vector element doesn't know from that pointer actually.

Sara
0
 

Author Comment

by:atomicgs12
ID: 35149584
"note, that doesn't apply for the pBuf input." Yes realize that thank so much.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now