I need create one pointer to a null-terminated array of pointers to key detail structures..
Struct: WFS_RESULT
typedef struct _wfs_result
{
REQUESTID RequestID;
HSERVICE hService;
SYSTEMTIME tsTimestamp;
HRESULT hResult;
union {
DWORD dwCommandCode;
DWORD dwEventID;
} u;
LPVOID lpBuffer;
} WFSRESULT, *LPWFSRESULT;
Struct: PINKEY
typedef struct _wfs_pin_key_detail_ex
{
LPSTR lpsKeyName;
DWORD dwUse;
BYTE bGeneration;
BYTE bVersion;
BYTE bActivatingDate[4];
BYTE bExpiryDate[4];
BOOL bLoaded;
} WFSPINKEYDETAILEX, * LPWFSPINKEYDETAILEX;
Program: How am i trying to do
LPWFSPINKEYDETAILEX* array[7];
LPWFSPINKEYDETAILEX Test;
WFSPINKEYDETAILEX Obj;
Test = &Obj;
Test->lpsKeyName = NULL;
array[0] = &Test;
array[1] = &Test;
array[2] = &Test;
array[3] = &Test;
array[4] = &Test;
array[5] = &Test;
array[6] = NULL;
LPWFSPINKEYDETAILEX** val = array;
lpWFSResult->lpBuffer = val;
The question is, is what I did above a pointer to an array of pointers? Because, I need to pass this Pointer Array Pointer to this parameter lpWFSResult-> lpBuffer = val; and in the final program (Bank Application) it gives error -15 (WFS_ERR_INTERNAL_ERROR).
Just as idea. Maybe they check if to be different objects. Maybe they are using the previous pointers and do not expect that value of val[0] will be changed after changing val[1].
Also check the API maybe they expects the rest of the fields filled up
lpsKeyName
bGeneration
bActivatingDate
bExpiryDate
This depends on how the array is created and where it is stored/used. based on the code provided, I assume the array has been generated on the memory stack but then used after that stack level has been popped (ie. function returns). The array memory will have been deallocated and the array pointer will be invalid (will cause unexpected behaviour). If you need to preserve the array outside of the stack, you will need to generate it on the heap using new. This way the memory will persist after the function exits and the memory stack level is popped.
LPWFSPINKEYDETAILEX** array = new LPWFSPINKEYDETAILEX*[7];
LPWFSPINKEYDETAILEX Test;
WFSPINKEYDETAILEX Obj;
Test = &Obj;
Test->lpsKeyName = NULL;
array[0] = &Test;
array[1] = &Test;
array[2] = &Test;
array[3] = &Test;
array[4] = &Test;
array[5] = &Test;
array[6] = NULL;
lpWFSResult->lpBuffer = array;
Don't forget to delete it later when you're done with the memory so you don't get a memory leak.
You need to read the API spec where it tells you how to allocate memory. I presume you are writing an SP, have six keys and the key names are in the array keyNames.
int numKeys=6;
LPSTR keyNames[6]={"key1","key2","key3","key4","key5","key6"};
LPWFSRESULT pResult;
LPWFSPINKEYDETAILEX* ppDetails;
WFMAllocateBuffer(sizeof(WFSRESULT), WFS_MEM_ZEROINIT, (LPVOID*)&pResult);
WFMAllocateMore(sizeof(LPWFSPINKEYDETAILEX)*(numKeys+1),pResult, (LPVOID*)&ppDetails);
for (int i=0;i<numKeys;i++)
{
WFMAllocateMore(sizeof(WFSPINKEYDETAILEX),pResult,(LPVOID*)&ppDetails[i]);
WFMAllocateMore(strlen(keyNames[i])+1,pResult,(LPVOID*)&ppDetail[i].lpsKeyName);
strcpy(ppDetails[i].lpsKeyName,keyNames[i]);
//TODO fill in other details
}
ppDetails[numKeys]=NULL;
pResult->lpBuffer=ppDetails;
Related
Environment: Windows 7 pro x64, Microsoft Visual Studio 2015 Enterprise, Version 14.0.25424.00 Update 3
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
std::string _orig2 = "[999 99% (1/1)O:999]";
char *orig = NULL;
char *orig2 = NULL;
orig = new char[_orig.length() + 1];
strcpy(orig, _orig.c_str());
orig2 = new char[_orig2.length() + 1];
strcpy(orig2, _orig2.c_str());
*orig++;
*orig2++;
int a = atoi(orig);
int b = atoi(orig2);
delete[] orig;
delete[] orig2;
return 0;
}
Running the above code crashes with the "_CrtIsValidHeapPointer(block)" error.
If I don't iterate (*orig++ and *orig2++), then no issues.
So my question is, how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
You did not delete the pointers you allocated!
delete must be called on the original memory address returned by new. Since you did orig++, you cant delete the address being pointed at!
Iterating can be done with an index, and using array subscription to dereference:
orig[i] = 'a';
Which is the same as doing this:
*(orig+i) = 'a';
Or you can get another pointer onto the same data, and modify this one.
char* pOrig = orig;
++pOrig;
Why did you write
*orig++; // why dereferencing?
Just ++ by itself would do the iteration.
Avoid to use raw pointers. Your code can be simpler:
std::string orig = "[188 80% (1/2)O:152]";
std::string orig2 = "[999 99% (1/1)O:999]";
int a = atoi(orig.c_str() + 1);
int b = atoi(orig2.c_str() + 1);
Your mistake is that you try to delete the shifted pointers instead of the original pointers. As the result heap manager gets wrong allocated block information usually put before the allocated pointer and you got heap corruption.
how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
Create a copy of the pointer:
char* orig = new char[size];
char* i = orig;
*i++ = 'a';
delete orig;
A perhaps more common idiom is to dereference a temporary:
for(int i = 0; i < size - 1; i++)
orig[i] = 'a';
I would love to [use std::string], but I need to use atoi(), which won't work on std::string
You are mistaken. atoi works with std::string just fine. Simply use std::string::c_str() just like you did with strcpy. There is absolutely no reason to allocate a block of memory with new.
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
int a = 0;
for (std::string::iterator it = _orig.begin(); it != _orig.end(); ++it)
{
if (isdigit((char)*it))
a = (atoi(it._Ptr));
}
return 0;
}
I got it. Thanks for everyone who helped me come to this conclusion. Staying with std::string was in fact the best approach.
I have the following code:
In Client.cpp there is the constructor that is doing memory allocation for the array "conturi" of type ContBancar.
Client::Client(string nume, string prenume, string adresa)
{
this->nume = nume;
this->prenume = prenume;
this->adresa = adresa;
nrCont = 0;
ContBancar** conturi = new ContBancar*[50];
}
Then there is a method that is adding a account in the "conturi" array:
void Client::adaugaCont(ContBancar* contNou)
{
conturi[nrCont++] = contNou;
}
This is my code in Main.cpp:
ContBancar ron1 ("1.r", 0, Banca::RON);
Client ioana ("Pop", "Ioana", "Str Dorobantilor 3/4");
ioana.adaugaCont(&ron1);
But it gives me the access violation error at runtime, like the array 'conturi' has no memory allocated. I don't understand why, because the memory should be allocated in the constructor.
Could anyone help me with this?
Client::Client(string nume, string prenume, string adresa)
{
this->nume = nume;
this->prenume = prenume;
this->adresa = adresa;
nrCont = 0;
//here is your problem!
ContBancar** conturi = new ContBancar*[50];
}
You redefine conturi as a new array, with the pointer to it stored in the local scope of the constructor.
Change the line to:
conturi = new ContBancar*[50];
and you will then have the object's conturi pointer pointing to the allocated memory.
This will also solve the memory leak you have introduced.
(pointer to heap goes out of scope. memory on heap is leaked)
Or even better, use a std::vector.
In Class definition:
std::vector<ContBancar> conturi;
You don't have to manage the memory yourself with new and delete and you are not restricted to a fixed number of elements either.
You're declaring a new pointer variable with the following line:
ContBancar** conturi = new ContBancar*[50];
and the pointer variable will get destroyed at the end of the function call and leak memory leaving any other same-name member variable untouched.
You should rather use the member variable conturi(assuming you have one from the rest of the code):
Client::Client(string nume, string prenume, string adresa)
{
this->nume = nume;
this->prenume = prenume;
this->adresa = adresa;
nrCont = 0;
conturi = new ContBancar*[50];
}
or you can use a std::vector<ContBancar> conturi member variable which might be easier to use and to deal with.
This is a simple reproducer to better understand the problem:
class Client {
public:
int** conturi = 0;
void function() {
int** conturi = new int*[50];
}
};
int main()
{
Client obj;
obj.function();
if(obj.conturi == 0)
std::cout << "this is still zero"; // This will get printed
}
Example
I am currently working on a project where I have to build a shell for a C++ dll, so a new C# GUI can use its functions.
However I got the following problem, in the C++ portion I have to create a new thread for specific reasons, and I want to pass an int array to the new thread.
Note that the values assigned to the array in the function in which this happens are gained from the C# portion of the code.
__declspec( dllexport ) void CreateReportPane(int &id, int &what)
{
DWORD threadId;
int iArray[2] = { id, what};
HANDLE hThread = CreateThread( NULL, 0, CreateReportPaneThread, iArray, 0, &threadId);
if (hThread == NULL)
{
ExitProcess(3);
}
}
The problem arises in the new thread, I can reliably fetch the first value out of the array, but the 2nd value seems to be released, here is the code on the other side.
DWORD WINAPI CreateReportPaneThread(LPVOID lparam)
{
int id, what;
id = *(( int * )lparam);
what = *(((int *)lparam)+1) ;
CreateReportPaneOriginal(id, what);
return 0;
}
Is there any way to prevent the values in the array from getting released while not holding the original thread captive?
A big thank you in advance
int iArray[2] = { id, what};
HANDLE hThread = CreateThread(...,CreateReportPaneThread, iArray, ...);
The problem is that iArray is a local array which means this gets destroyed when the function CreateReportPane() returns. So what CreateReportPaneThread() refers to doesn't exist. You get the first value just by chance. There is no such guarantee that you would get even the first value.
Use dynamic array:
int * iArray = new int[2];
iArray[0] = id;
iArray[1] = what;
HANDLE hThread = CreateThread(...,CreateReportPaneThread, iArray, ...);
Remember to write deallocate the array once you're done with it in CreateReportPaneThread:
DWORD WINAPI CreateReportPaneThread(PVOID *data)
{
int *array = static_cast<int*>(data);
int id = array[0], what = array[1];
delete []array; //MUST DO IT to avoid memory leak!
//rest of your code
}
Dynamically allocate the array to prevent the array going out of scope when CreateReportPane() exits:
int* iArray = new int[2];
iArray[0] = id;
iArray[1] = what;
otherwise the thread is accessing an array that is no longer valid, which is undefined behaviour. The thread routine CreateReportPaneThread() must then delete[] the array when it is no longer required (note the use of delete[] and not delete).
I want my function to return a BYTE array. The function is as follows.
BYTE sendRecieveData(BYTE control, unsigned int value){
//Open connection to LAC
HANDLE LACOutpipe;
HANDLE LACInpipe;
LACOutpipe=openConnection(MP_WRITE);
LACInpipe=openConnection(MP_READ);
//declare variables
BYTE bufDataOut[3];
BYTE bufDataIn[3];
DWORD bufInProcess;
DWORD bufOutProcess;
//sets CONTROL
bufDataOut[0]=control;
//sets DATA to be sent to LAC
BYTE low_byte = 0xff & value;
BYTE high_byte = value >> 8;
bufDataOut[1]=low_byte;
bufDataOut[2]=high_byte;
MPUSBWrite(LACOutpipe,bufDataOut,3,&bufOutProcess,1000);
MPUSBRead(LACInpipe,bufDataIn,3,&bufInProcess,1000);
MPUSBClose(LACOutpipe);
MPUSBClose(LACInpipe);
return bufDataIn[3];
}
It doesn't return a byte array and when I change BYTE to BYTE[] or BYTE[3] it gives me an error.
return bufDataIn[3]; means "return 4th element of bufDataIn array" and in this case it leads to undefined behaviour since the size of this array is 3.
You can allocate memory for this new array in the body of your function and return pointer to its first element:
BYTE* createArray(...)
{
BYTE* bufDataOut = new BYTE[3];
....
return bufDataOut;
}
Don't forget to delete it when you finish with it:
{
BYTE* myArray = createArray(...);
...
delete[] myArray;
}
Even better, use std::vector<BYTE> and get rid of this ugly memory management with it ;) This ensures that the memory is properly freed on any return path, even when exceptions are thrown.
Since your array is relatively small I'd recommend to pass your buffer as a function argument.
void sendRecieveData(BYTE control, unsigned int value, BYTE (&buffdataIn)[3] ).
Now, one will use this function as follows:
BYTE result[3] = {0};
sendRecieveData(3, 0, result);
This way you may avoid usage of dynamic memory allocation and make your code safer.
char *p = new char[200];
char *p1 = p;
char *p2 = &p[100];
delete [] p1;
Btw this is not a test or anything i actually need to know this :)
// allocate memory for 200 chars
// p points to the begining of that
// block
char *p = new char[200];
// we don't know if allocation succeeded or not
// no null-check or exception handling
// **Update:** Mark. Or you use std::no_throw or set_new_handler.
// what happens next is not guranteed
// p1 now points to the same location as p
char *p1 = p;
// another pointer to char which points to the
// 100th character of the array, note that
// this can be treated as a pointer to an array
// for the remaining 100-odd elements
char *p2 = &p[100];
// free the memory for 200 chars
delete [] p1;
// **Update:** Doug. T
// [...] p and p2 are now pointing to freed memory
// and accessing it will be undefined behavior
// depending on the executing environment.