Deleting dynamically sized array from function - c++

In this part of my code (receiving the time) I have a dynamically sized array of chars. This is for a school project and dynamically sized arrays are required.
char* msgtime::getTime() {
std::string t;
t.append(std::to_string(hour));
t.append(":");
t.append(std::to_string(minute));
char *charTime = new char[t.length()];
strcpy(charTime, t.c_str());
return charTime;
}
However, I can't delete the charTime since I am returning the value. I tried following another question I saw on here to return it into a char* in the main program then delete that when I'm done with it. The code here is what the function is returning to:
void receive(packet &data, SOCKET con) {
msgtime tim;
cout << "Receiving data" << endl;
int in = recv(con, (char*)&data, sizeof(data), 0);
cout << "Data received: " << in << endl;
tim.updateTime();
char *newTime = tim.getTime();
strcpy(data.time, newTime);
delete[] newTime;
}
Except when I run it I get this error:
HEAP CORRUPTION DETECTED: after Normal block (#183) at 0x00129330
CRT detected that the application wrote to memory after the end of heap buffer.
I need to delete the charTime in the getTime function to plug the memory leak but I can't figure out how to do it. Any help is GREATLY appreciated!

You don't allocate enough space, one more char is required to store null terminator:
char *charTime = new char[t.length() + 1];

Related

Passing default string pointer to function

there is a prototype of a function in my fuu.h. I want to pass default values if there
void MyFunction(
int iError = 0,
std::string * MyProblemString = ""
);
// Some attemts:
void MyFunction(
int iError = 0,
std::string * MyProblemString = std::string{""}; // does not work to, complains about missing '*'
);
void MyFunction(
int iError = 0,
std::string * MyProblemString = &std::string{""}; // does not work to, refering address to temporary value
);
void MyFunction(
int iError = 0,
std::string * MyProblemString = *std::string{""}; // does not work to, overloaded operator not known
);
void MyFunction(
int iError = 0,
std::string * MyProblemString = ""; // could not convert ‘""’ from ‘const char [1]’ to ‘std::__cxx11::string* {aka std::__cxx11::basic_string<char>*}’
);
in my c-file is written:
void MyFunction(
int iError,
std::string * MyProblemString,)
{
// do some stuff
}
With the int it's working fine. How can I make the same thing with the string?
There are some examples with other constructions, but passing a pointer does not work.
const reference default-value
thx
I don't think you understand what pointers do. I'll try to help.
Pointers
int number; // An int
int * pointer; // A valid pointer to an int
int* pointer; // Also a valid pointer to an int
int *pointer; // Also a valid pointer to an int
"number" is a named variable of type integer with a chunk of memory big enough to store an int assigned to it. This chunk of memory is given a memory address.
Pointers are basically like an int, except the number they store is the memory address of another variable - in your case, "number".
The & operator will give you the memory address of the variable you use it on.
&number
This will give you the memory address of your int "number".
pointer = &number; // Pointer now contains the memory address of "number"
Now if you try to use pointer like an int, it will give you the address of "number", not its contents. To access the contents of whatever your pointer is pointing at, prefix it with *.
void main()
{
int number = 56;
int* pointer = number; // INVALID: Pointer now pointing at memory location "56"
int* pointer = &number; // Valid: Pointer now pointing at memory location of number
int* pointer; // DANGEROUS, DO NOT LEAVE HANGING POINTERS -- leads to memory access violations
int *pointer = nullptr; // Safely initialise unused pointer
int size = 32;
pointer = new int; // Allocates a block of memory the size of 1 int. Pointer now points at this memory
pointer = new int[size]; // Allocates an array of 32 ints to pointer. Pointer now points to this block of memory
pointer = new int[8]; // Allocates another array to pointer. Pointer now points at the new array, old array has nothing pointing at it and is lost in memory!
// This is a memory leak. AVOID MEMORY LEAKS AT ALL COSTS, they can produce some of the hardest-to-find bugs you'll come across
delete pointer; // Deletes chunk of memory the size of 1 int at the memory pointer is pointing at
delete[] pointer; // Deletes array of memory following the location pointer is pointing at
// IMPORTANT: ALWAYS use delete with new, delete[] with new[]
// IMPORTANT: NEVER use new or new[] without its delete counterpart, or you will encounter memory leaks
// USEFUL:
if (pointer != nullptr)
{
// Do stuff
}
// Doing this will ensure you don't act upon memory you aren't supposed to mess with
// Print these to console to gain a better understanding.
std::cout << number << std::endl;
std::cout << &number << std::endl;
std::cout << pointer << std::endl;
std::cout << *pointer << std::endl;
system("pause");
}
Pay attention to the output:
Output on my machine (the address will vary when you run it):
56 // number
0035F7E0 // &number
0035F7E0 // pointer
56 // *pointer
Note that "&number" and "pointer" print the same thing
You can use & and * to assign pointers to anything, including pointers to other pointers to other pointers to other pointers to whatever the hell you want. It gets messier the deeper you go with things like that, but the point is (pun unintended) pointers are one of the most versatile and handy (but also dangerous -- MEMORY LEAKS, ACCESS VIOLATIONS, AHHH) things to use in C++.
Hope this helped, post a reply to this answer if you don't understand or if this didn't help you understand your problem.
The problem you are having is because you can't give a default value to a pointer without dealing with the memory the pointer is supposed to point to. If you use a std::string instead of a pointer to std::string then you can use the simple string literal syntax as in MyFunction().
If you need to pass a pointer to a string, because you are planning to manipulate the string or for some other purpose, you can give the string the default value of NULL. Since NULL does not point to any memory, this is a perfectly sane default for a pointer. Then you can check for this value, and allocate a new std::string in that special case. That is what I am doing in MyFunction2.
HOWEVER if you allocate memory, you must free that memory somewhere. In my example, I am freeing the memory inside of MyFunction2 only if I also created it. If the value was supplied, I am not freeing the value, but rather leaving that up to the calling function. How you manage memory will depend on your use case, but don't forget about this crucial step.
#import <iostream>
void MyFunction(
int iError = 1,
std::string MyProblemString = std::string(""))
{
std::cout << "\tiError = " << iError << ", and MyProblemString = " << MyProblemString << std::endl;
}
void MyFunction2(
int iError = 1,
std::string * MyProblemString = NULL)
{
bool shouldFree = MyProblemString == NULL;
if (shouldFree){
MyProblemString = new std::string("");
}
std::cout << "\tiError = " << iError << ", and MyProblemString = " << *MyProblemString << std::endl;
if(shouldFree){
delete MyProblemString;
}
}
int main(){
std::string * test = new std::string("test");
std::cout << "Testing with MyFunction:" << std::endl;
std::cout << "\tTest default arguments:" << std::endl;
MyFunction();
std::cout << "\tTest only first argument:" << std::endl;
MyFunction(0);
std::cout << "\tTest both arguments" << std::endl;
MyFunction(2, *test);
std::cout << std::endl;
std::cout << "Testing with MyFunction2:" << std::endl;
std::cout << "\tTest default arguments:" << std::endl;
MyFunction2();
std::cout << "\tTest only first argument:" << std::endl;
MyFunction2(0);
std::cout << "\tTest both arguments" << std::endl;
MyFunction2(2, test);
delete test;
}

How to properly access the data of a unsigne char pointer in C++?

I need to write a series of classes that will simulate some hardaware behaviour. To properly interface with the rest of the program my class needs to use unsigned char * bb as an input. Since I've never worked with this particular type before I created the following test program just to see how to access/interpret the data:
// This will be the test bench
int main() {
unsigned char * bytebuffer = new unsigned char[100];
bytebuffer = (unsigned char *) 548;
InstructionDeco deco(bytebuffer);
return 0;
}
And the constructor has:
InstructionDeco::InstructionDeco(unsigned char *bb){
cout << "Hola" << endl;
if (bb){
cout << "Not NULL" << endl;
}
else{
cout << "Si es NULL" << endl;
}
cout << "El BB es " << bb << endl;
}
This tells me that the pointer is Not NULL, but no matter how I change the line
bb << endl
To bb[0] or *bb or *bb[0] I allways get a segmetation fault at that line. I'm thinking that I don't know how to properly access the data.
What am I doing wrong?
You are trying to dereference a pointer to address 548, which is an invalid address.
unsigned char * bytebuffer = new unsigned char[100];
bytebuffer = (unsigned char *) 548;
You asked to allocate 100 bytes and the pointer of that area was put in bytebuffer - Line 1.
But then you override (why???) the address of the allocated area and instead of that address you put 548 - Line 2 (causing memory leak because now you lost the pointer to the allocated area and won't be able to release it later).
When you try to access the bb by *bb or bb[0] you actually try to access the data at address 548. Most likely that this address doesn't belong to your process so you get a segmentation fault.
Probably the problem is in bytebuffer = (unsigned char *) 548; line. You assign a pointer a 548 value. This isn't allocated memory, that's why you get segfault.

How can I check if there is enough heap memory available?

I have an assignment that requires me to create a "Heap" class that allocates and deallocates memory. I believe that my code works and the solution builds and runs properly but I want to make sure that I am not getting any memory leaks. I also need to add some code that checks if the desired amount to be allocated to the heap is even available...if someone were to allocate a very large amount. How is it possible to check if the memory allocated on the heap is available or NULL if there is not enough memory. Here is my code so far:
#include <iostream>
using namespace std;
class Heap{
public:
double* allocateMemory(int memorySize)
{
return new double[memorySize];
};
void deallocateMemory(double* dMemorySize)
{
delete[] dMemorySize;
};
};
int main()
{
Heap heap;
cout << "Enter the number of double elements that you want to allocate: " << endl;
int hMemory;
const int doubleByteSize = 8;
cin >> hMemory;
double *chunkNew = heap.allocateMemory(hMemory);
cout << "The amount of space you took up on the heap is: " <<
hMemory*doubleByteSize << " bytes" <<
starting at address: " << "\n" << &hMemory << endl;
heap.deallocateMemory(chunkNew);
system("pause");
return 0;
}
It's not necessary to check beforehand, just try to allocate memory and if you can't, then catch the exception. In this case it is of type bad_alloc.
#include <iostream>
#include <new> // included for std::bad_alloc
/**
* Allocates memory of size memorySize and returns pointer to it, or NULL if not enough memory.
*/
double* allocateMemory(int memorySize)
{
double* tReturn = NULL;
try
{
tReturn = new double[memorySize];
}
catch (bad_alloc& badAlloc)
{
cerr << "bad_alloc caught, not enough memory: " << badAlloc.what() << endl;
}
return tReturn;
};
Important note
Be sure to guard against double-freeing memory. One way to do that would be to pass your pointer to deallocateMemory by reference, allowing the function to change the pointer value to NULL, thereby preventing the possibility of delete-ing the pointer twice.
void deallocateMemory(double* &dMemorySize)
{
delete[] dMemorySize;
dMemorySize = NULL; // Make sure memory doesn't point to anything.
};
This prevents problems like the following:
double *chunkNew = heap.allocateMemory(hMemory);
heap.deallocateMemory(chunkNew);
heap.deallocateMemory(chunkNew); // chunkNew has been freed twice!

Maximum memory that can be allocated dynamically and at compile time in c++

I am playing around to understand how much memory can be allocated. Initially I thought that the maximum memory which can be allocated is equal to Physical memory (RAM). I checked my RAM on Ubuntu 12.04 by running the command as shown below:
~$ free -b
total used free shared buffers cached
Mem: 3170848768 2526740480 644108288 0 265547776 1360060416
-/+ buffers/cache: 901132288 2269716480
Swap: 2428497920 0 2428497920
As shown above,total physical memory is 3Gig (3170848768 bytes) out of which only 644108288 bytes is free, so I assumed I can at max allocate only this much memory. I tested it by writing the small program with only two lines below:
char * p1 = new char[644108290] ;
delete p1;
Since code ran perfectly , it means it allocated memory successfully. Also I tried to allocate the memory greater than the available physical free memory still it did not throw any error. Then per question
maximum memory which malloc can allocate
I thought it must be using the virtual memory.So I tested the code for free swap memory and it also worked.
char * p1 = new char[2428497920] ;
delete p1;
The I tried to allocate the free swap plus free RAM bytes of memory
char * p1 = new char[3072606208] ;
delete p1;
But this time code failed throwing the bad_alloc exception.Why the code didn't work this time.
Now I allocated the memory at compile time in a new program as shown below:
char p[3072606208] ;
char p2[4072606208] ;
char p3[5072606208];
cout<<"Size of array p = " <<sizeof p <<endl;
cout<<"Size of array p2 = " <<sizeof p2<<endl;
cout<<"Size of array p2 = " <<sizeof p3;
The out put shows
Size of array p = 3072606208
Size of array p1 = 4072606208
Size of array p2 = 777638912
Could you please help me understand what is happening here. Why did it allowed the memory to be allocated at the compile time but not at dynamically.
When allocated compile time how come p and p1 were able to allocate memory greater than swap plus free RAM memory. Where as p2 failed.
How exactly is this working. Is this some undefined behaviour or os specific behaviour. Thanks for your help. I am using Ubuntu 12.04 and gcc 4.6.3.
Memory pages aren't actually mapped to your program until you use them. All malloc does is reserve a range of the virtual address space. No physical RAM is mapped to those virtual pages until you try to read or write them.
Even when you allocate global or stack ("automatic") memory, there's no mapping of physical pages until you touch them.
Finally, sizeof() is evaluated at compile time, when the compiler has no idea what the OS will do later. So it will just tell you the expected size of the object.
You'll find that things will behave very differently if you try to memset the memory to 0 in each of your cases. Also, you might want to try calloc, which zeroes its memory.
Interesting.... one thing to note: when you write
char p[1000];
you allocate (well, reserve) 100 bytes on the stack.
When you write
char* p = malloc(100);
you allocate 100 bytes on the heap. Big difference. Now I don't know why the stack allocations are working - unless the value between the [] is being read as an int by the compiler and is thus wrapping around to allocate a much smaller block.
Most OSs don't allocate physical memory anyway, they give you pages from a virtual address space which remains unused (and therefore unallocated) until you use them, then the memory-manager unit of the CPU will nip in to give you the memory you asked for. Try writing to those bytes you allocated and see what happens.
Also, on windows at least, when you allocate a block of memory, you can only reserve the largest contiguous block the OS has available - so as the memory gets fragmented by repeated allocations, the largest side block you can malloc reduces. I don't know if Linux has this problem too.
There's a huge difference between these two programs:
program1.cpp
int main () {
char p1[3072606208];
char p2[4072606208];
char p3[5072606208];
std::cout << "Size of array p1 = " << sizeof(p1) << std::endl;
std::cout << "Size of array p2 = " << sizeof(p2) << std::endl;
std::cout << "Size of array p3 = " << sizeof(p3) << std::endl;
}
program2.cpp:
char p1[3072606208];
char p2[4072606208];
char p3[5072606208];
int main () {
std::cout << "Size of array p1 = " << sizeof(p1) << std::endl;
std::cout << "Size of array p2 = " << sizeof(p2) << std::endl;
std::cout << "Size of array p3 = " << sizeof(p3) << std::endl;
}
The first allocates memory on the stack; it's going to get a segmentation fault due to stack overflow. The second doesn't do much at all. That memory doesn't quite exist yet. It's in the form of data segments that aren't touched. Let's modify the second program so that the data are touched:
char p1[3072606208];
char p2[4072606208];
char p3[5072606208];
int main () {
p1[3072606207] = 0;
p2[3072606207] = 0;
p3[3072606207] = 0;
std::cout << "Size of array p1 = " << sizeof(p1) << std::endl;
std::cout << "Size of array p2 = " << sizeof(p2) << std::endl;
std::cout << "Size of array p3 = " << sizeof(p3) << std::endl;
}
This doesn't allocate memory for p1, p2, or p3 on the heap or the stack. That memory lives in data segments. It's a part of the application itself. There's one big problem with this: On my machine, this version won't even link.
The first thing to note is that in modern computers is that processes do not get direct access to RAM (at the application level). Rather the OS will provide each process with a "virtual address space". The OS intercepts calls to access virtual memory reserves real memory as and when needed.
So when malloc or new says it's found enough memory for you, it just means that its found enough memory for you in the virtual address space. You can check this by running the following program with the memset line and with it commented out. (careful, this program uses a busy loop).
#include <iostream>
#include <new>
#include <string.h>
using namespace std;
int main(int argc, char** argv) {
size_t bytes = 0x7FFFFFFF;
size_t len = sizeof(char) * bytes;
cout << "len = " << len << endl;
char* arr = new char[len];
cout << "done new char[len]" << endl;
memset(arr, 0, len); // set all values in array to 0
cout << "done setting values" << endl;
while(1) {
// stops program exiting immediately
// press Ctrl-C to exit
}
return 0;
}
When memset is part of the program you will notice the memory used by your computer jumps massively, and without it you should barely notice any difference if any. When memset it called is accessed all the elements of the array, forcing the OS to make the space available in physical memory. Since the argument for new is a size_t (see here) then the maximum argument you can call it with is 2^32-1, though this isn't guaranteed to succeed (it certainly doesn't on my machine).
As for your stack allocations: David Hammem's answer says it better than I could. I am surprised you were able to compile those programs. Using the same setup as you (Ubuntu 12.04 and gcc 4.6) I get compile errors like:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:14:6: error: size of variable ‘arr’ is too large
try the following code:
bool bExit = false;
unsigned int64 iAlloc = 0;
do{
char *test = NULL;
try{
test = new char[1]();
iAlloc++;
}catch(bad_alloc){
bExit = true;}
}while(!bExit);
char chBytes[130] = {0};
sprintf(&chBytes, "%d", iAlloc);
printf(&chBytes);
In one run don't open other programms, in the other run load a few large files in an application which use memory mapped files.
This may help you to understand.

Placing floats from string into void array

I get a segmentation fault when my function reads floats from a string and places them in a void array. The segfault occurs after about 200 iterations of the for loop in the following code:
// Allocate memory
void** data;
data = (void**)malloc(num_vals * sizeof(float));
// Convert text to floats
(*(float**)data)[0] = atof(strtok(text, " "));
for(int index=1; index<num_vals; index++) {
(*(float**)data)[index] = atof(strtok(NULL, " "));
std::cout << (*(float**)data)[index] << std::endl;
}
The void array is necessary because the size and type of data in the string are determined at run-time. I've tried increasing the malloc size, but it doesn't change anything. Any thoughts?
Seriously??
std::vector<float> data;
std::istringstream str(text);
float fv;
while (str >> fv)
{
data.push_back(fv);
}
Now that's c++
As much as it pains me to do so, here is a version of your code that probably does what you want.
// Allocate memory
void* data;
data = malloc(num_vals * sizeof(float));
// Convert text to floats
((float*)data)[0] = atof(strtok(text, " "));
for(int index=1; index<num_vals; index++) {
((float*)data)[index] = atof(strtok(NULL, " "));
std::cout << ((float*)data)[index] << '\n';
}
Note, however, that if you worked for me and tried to check in that code, we would have a serious discussion about your choice of career.
I'd rather see something like this:
std::vector<float> v;
std::copy(std::istream_iterator<float>(std::istringstream(text)),
std::istream_iterator<float>(),
std::back_inserter(v));
P.s. Rob's rule #47: Never say std::endl when you mean '\n'.
Why do you convert to void ** ??? You code contains couple errors on indexing, so let me show some reasonable changes
float* data;
data = (float*)malloc(num_vals * sizeof(float));
// Convert text to floats
data[0] = atof(strtok(text, " "));
for(int index=1; index<num_vals; index++) {
data[index] = atof(strtok(NULL, " "));
std::cout << data[index] << std::endl;
}
You got your types mixed up in your inexplicable attempt to create this monster under the pretence of writing "C++". Anyway. what you're mallocing is nothing but a float*, so you need to cast data back to float*:
((float*)data)[0] = myfloat;
I think, since you are defining a pointer of void pointer and allocating/casting it to pointer of void pointer, it allocates 4 byte memory for each element because in C/C++, regardles of the type of the pointer, pointers are always 4 bytes which are not big enough floats.
There're several issues. One is - data should be void *, you have redundant *. Other might be alignment, i'm not sure you are able to place a float in any location in the memory.