What would this code do? (memory management) - c++

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.

Related

free(): double free detected in tcache 2 while deleting dynamic array [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am trying to read a .txt file and print the lines, while using only c-style string.
int main(int argc, char * argv[]){
...
size_t size = 2;
char* line = new char[size];
char c;
while (file.get(c)) {
if(c != '\n'){
line[size - 2] = c;
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
size++;
} else{
line[size - 1] = '\n';
cout << line << endl;
delete [] line;
size = 2;
line = new char[size];
}
}
...
}
I am getting the error free(): double free detected in tcache 2. What is the problem and how can fix it?
I am getting the error free(): double free detected in tcache 2. What
is the problem and how can fix it?
By understanding the error in this code:
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
The important thing to remember is that temp and line are pointers to an array of chars; that is they can refer to an array but they do not (by themselves) represent copies of the array. So:
// sets (line) to a memory address where (size) bytes have been
// made available for you to use. Let's assume (line) gets set to
// 0x11223344
char* line = new char[size];
[...]
// sets (temp) to the memory address where (size+1) bytes have been
// made available for you to use. For the sake of the exmaple,
// let's assume (temp) gets set here to memory-address 0x12345678.
char* temp = new char[size + 1];
// Copies (size) bytes from (line) (aka starting at memory-address 0x11223344)
// to (temp) (aka starting at memory-address 0x12345678)
memcpy(temp, line, size * sizeof(char));
// tells the heap that you no longer need the byte-array starting at 0x11223344.
// After this delete[] returns, the heap is allowed to reuse those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] line;
// Sets the value of the (line) pointer to point to 0x12345678 instead.
line = temp;
// tells the heap that you no longer need the bytes starting at 0x12345678.
// After this delete[] returns, the heap is allowed to use those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] temp;
// Note that at this point, (line) is still pointing to 0x1234568, *but*
// you are no longer allowed to use the memory at that address!
// This is a problem, because on the next iteration of your while-loop,
// you are going to write to either line[size-2] or line[size-1]; either
// either way you are writing to freed memory, which will invoke
// undefined behavior and cause problems for you.
So, how to fix this? As suggested in the comments, the best way to fix it would be to avoid new and delete[] entirely, and stick to using std::string instead, since that would avoid all the usual problems with dangling pointers, use-after-free, uninitialized-memory-reads, unterminated strings, etc.
If you must use new and delete[], however (e.g. because that's the rules of the assignment), then you need to keep track of the lifetime of each of your heap allocations; in this case, that means realizing that when you set line = temp;, that means that line is now pointing to the same array temp is pointing to, and since your code wants to use that array in the future, you shouldn't call delete[] temp; as that deletes the heap-allocation that line was pointing to, and leaves line as a dangling-pointer (i.e. pointing to memory you are no longer permitted to use).

C++ dynamic alocate, pointers

I get this error :
"crt detected that the application wrote to memory after end of heap
buffer"
this program should write every second sign...
char x = 1;
while ( x != 0) {
char *ptr(0);
ptr = new char;
fgets(ptr, 100001, stdin);
for (char i = 0; i < sizeof(ptr); i++) {
cout << *(ptr + i);
i++;
}
cout << endl;
delete ptr;
ptr = 0;
}
ptr = new char; allocates exactly one byte for the pointer. Than fgets(ptr, 100001, stdin); attempts to read up to 100001 characters into it, obviously well beyond it's allocated boundary.
The immediate solution would be to make sure you allocate the buffer with adequate size using array form of new, i.e. ptr = new char[100001];. This, in turn, will lead to changing the delete into it's array form as well: delete[] ptr
Also, keep in mind that sizeof(ptr) will give you the size of the pointer (4 or 8 bytes on most platforms). You would want to use strlen or similar to find out when the string ends.
All suggestions above should be taken in light of the learning exercise. In real life, you should not do this, and instead use std::string and modern ways of string-oriented reading. (std::getline would be the most readily available).
sizeof returns size in bytes of the object representation of type. https://en.cppreference.com/w/cpp/language/sizeof
One other point major point to note is that ptr = new char will only allocate exactly one byte from the heap. But in your code you are trying to read 100001 bytes and obviously this is beyond the accessible memory range of that pointer.
you can modify the error as ptr = new char[100001]; When you do this, there is another change that you must do in order to avoid memory leaks.
That being, delete[] ptr. Because you have allocated 100001 adjacent bytes, you have to de-allocate them all.

Pointer to array of structs pointers

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;

Deleting a temporal Array in C++

I was working with dynamic memory from a book that I got. As far as I understand every time that we create a new variable we need to delete it, and set the pointer to null, so we don't have dangling pointers .
I created a program that stores values from users in a dynamic Array of [5], and whenever the user adds more I "expand" the array. When expanding, I use a temporary new array that gives me a tough time when I try to delete it. Why does this happen?
size_t arraySize(5), index(0);
int inputvalue(0);
int *ptemporal(nullptr);
int *pvalues = new int[arraySize];
for (;;){
cout << "Enter value or 0 to end: ";
cin >> inputvalue; //enter value
// exit loop if 0
if (!inputvalue) //if 0 break
break;
pvalues[index++] = inputvalue; //store values on pivalores
if (index == arraySize){ //if limit reached create space
cout << "Limit reached. Creating space...";
arraySize += 5; //5 new memory blocks
ptemporal = new int[arraySize]; //temporal value holder.
for (size_t i = 0; i < arraySize - 5; i++) //xfer values to temporal
ptemporal[i] = pvalues[i];
delete[] pvalues; // delete values to
pvalues = ptemporal; // assigning the same addres to pvalues.
**delete[] ptemporal; //causes a problem if I use the delete. if i comment the program works just fine.**
ptemporal = nullptr;
}
}
return 0;
}
**The two asterics are just to show were the problem occurs.
Your issue is that you are deleting ptemporal right after you copy the pointer to pvalues:
pvalues = ptemporal; // assigning the same addres to pvalues.
delete[] ptemporal; //causes a problem if I use the delete. if i commentt the program works just fine.**
In other words, you delete the memory you just created! So the next time you expand the vector, you try to delete it again, resulting in a double free error. This sort of error is where a debugger helps, so you can watch the variable values as your program executes.
// start
ptemporal = nullptr;
pvalues = /* location A */;
// first expansion
ptemporal = /* location B */;
// copy values from location A to B
delete[] pvales; /* location A */
pvalues = ptemporal; /* location B! */
delete[] ptemporal; /* location B */
ptemporal = nullptr;
// second expansion
ptemporal = /* location C */;
// copy values from location B to C, should segfault
// then you delete pvalues (aka location B) again!
// this results in a double free error
delete[] pvales; /* location B */
To fix this, simply remove the line delete[] ptemporal;
You dont need to delete pTemporal. You've deleted pValues and wish to hand over pTemporal into it.
delete [] pValues;
pValues = pTemporal;
pTemporal = NULL;

Undetected error with new operator

I was messing around trying to understand pointers and the operator "new"
and I ended up getting even more confused on what these 2 codes should result to, which is other but its not, so I wanted to understand what happened here.
thanks in advance.
#include <iostream>
using namespace std;
int main()
{
int * p = new int(50);
p[1] = 33;
cout << *p << endl;
}
Output: 50
and when I tried this
#include <iostream>
using namespace std;
int main()
{
int * p = new int[50];
p[1] = 33;
cout << *p << endl;
}
Output: -842150451
I was wondering about the meaning of each result.
In the first case
int * p = new int(50); // allocates 1 int on heap, initialized to value of 50
p[ 1] = 33; // p gives you the address of integer,
// p[1] moves the p pointer forward and accessing
// the pointed object results in undefined behavior,
// this means that at this moment anything can happen
// exception, crash, home war, nothing, everything,
// printing garbage value as well
In the second case:
int* p = new int[50]; // allocates 50 ints on heap, uninitialized
p[ 1] = 17; // initializes element with index 1 to value of 17
std::cout << *p; // p gives you the address of first element, with index 0
// which is still uninitialized, thus prints garbages
You should use
int* p = new int[50]();
to value-initialize ints to 0.
In the first one, you created dynamically a single int with a value of 50. When you try to assign the value 33, you actually assign it in memory that is not yours. It is undefined behaviour. But when you print it, you print the original value you made, which was 50.
In the second one, you created dynamically an array of 50 int. You've then specified the second value of in the array should be 33.* So when you print the value with cout << *p << endl;, you end up printing only the first value, which is undefined. Try it again, you'll probably get another value.
*Edit: as pointed in the comments, I should have been more explicit about this. An array starts at 0. So if you want to access the first value p[0] would do it.
In the first case you're creating an array of 50 ints, assigning a value to the SECOND int in the array, and then printing the first element in the array. Array indices start at 0, so when you dereference the pointer in your cout statement, it's printing whatever happened to be in memory at index 0.
In the second case you're creating a single integer, and initializing it with the value 50. When you dereference the pointer in the print statement, you're getting the integer you just created. The p[1] = 33 may or may not cause an error as your accessing unassigned memory.
int* p = new int[50];
allocates an array of int on the heap with 50 uninitialized elements, ranging from index 0 to 49.
Setting p[1] to 33 doesn't change p[0] which is what you're printing with "cout << *p".
The value -842150451 (0xCDCDCDCD in hex) is a magic number "Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory", see this question on SO.
int* p = new int(50);
allocates exactly one int on the heap and initializes it with the value 50, so setting p[1] afterwards should result in undefined behavior since you didn't allocate that memory where p[1] is referring to.
I'd recommend to use the Visual Studio Memory Windows to see what happens to the memory you're allocating while stepping through your code.