I use new to allocate a buffer, as follows:
BYTE *p;
p = new BYTE[20];
If I do NOT store the size of the allocated buffer, how to determine the buffer size via p only?
You can't as p is just a pointer to the blocks of memory allocated. You have to keep count of how much memory you allocated.
You have to store the size of the allocated buffer in a variable if you want access to it later. After those statements, you'll only have access to the pointer, which can't tell you how many elements are in the buffer.
Related
I am working on a memory manager for a school assignment. The jist of the assignment is you allocate a large character array, then split that array up into blocks which the client can "allocate" or "free."
Part of the assignment involves header blocks, a little block of information before each block about the block. It basically tracks information about the block. One of the types of header blocks we need to implement is an external header block. For the external header block, instead of storing the header data in the block itself, we need to dynamically allocate a to struct with the header data. The problem is further complicated by the struct having a dynamically allocated label.
My teacher's driver is getting null when it tries to access the data, and when I delete the data, it throws an access violation, probably because I'm not storing the data in the raw memory properly.
In essence, the problem is: I need to dynamically allocate a struct with a dynamically allocated string and then put a pointer to that struct in the first 8 bytes of a block of raw memory.
Here is my current implementation
char* newString = new char[strlen(inputString)];
//Copy the label passed into this fx into the allocated memory
strcpy(newString, inputString);
//Allocate and initalize the struct
headerStruct* pHeader = new headerStruct;
pHeader->active = true;
pHeader->string = newString;
//Save the first 8 bytes of my block of memory as a headerStruct*
headerStruct* hAddress = reinterpret_cast<headerStruct(*)>(address);
//Make the first 8 bytes point to the recently allocated struct
hAddress = pHeader;
If I'm following this right, the headerLoc in you allocation needs to be a pointer to a pointer, since you need to store a pointer to the memory block at address:
MemBlockInfo** headerLoc = reinterpret_cast<MemBlockInfo **>(address);
Then dereference it properly to store header there.
How to manage memory in function, which returns dynamically allocated variable?
What happens with buffer, when function returns?
char * getStr(){
char * buffer = new char[12];
sprintf_s(buffer, 12 , "abcdef");
return buffer;
}
buffer stays allocated, but luckily you're returning the pointer.
You must delete[] that pointer at some point, else you'll leak memory.
Notice how I've used []: that's important. This balances your allocation of an array of chars. (Conceptually the runtime stores the length of an array allocated with new something[], and delete[] informs the runtime to free the correct number of elements.)
When function returns, your buffer still exists. There is nothing like embedded memory manager, you MUST free all the memory you allocated manualy. That is about C.
In C++ standart library, there is objects called smart pointers. With the pressence of exceptions, they are totally recommended to use. There is fine answer on SO about them: What is a smart pointer and when should I use one?
Nothing.
The address which is stored in *buffer will be returned to the caller and it is up to the caller to delete the memory again.
buffer is a pointer that means it addresses a point in memory.
new will allocate a bloc of memory, for the command new char[12] it will allocate 12 chars worth of memory.
new returns the address of the memory and that is assigned to your pointer buffer.
Note that because you only have a pointer to the memory, you need to clean that up before buffer goes out of scope. If the address contained in buffer buffer goes out of scope you will have "leaked" memory. Because it cannot be reclaimed. You clean up the memory allocated by new char[12] with the command: delete[].
Thank to Bathsheba for his answer.
My vision of a solution to the problem:
char * getStr(){
char * buffer = new char[12];
sprintf_s(buffer, 12 , "abcdef");
return buffer;
}
int _tmain(int argc, _TCHAR* argv[]){
char * p = getStr();
std::cout << p << std::endl;
delete[] p;
return 0;
}
Is there any memory leak ?
const char * pname = "NAME";
char * temp = new char[strlen(Name) + 64];
sprintf(temp,"%s", pname);
delete [] temp; // is there any memory leaks because now length of temp is 4.
It is undefined behavior to delete(modify) string literal(pname).
Also new/delete, new []/delete[] are only used in pair.
Suggest use std::string if you could, let std::string manage the memory allocation/deallocation for you.
std::string pname("NAME");
std::string temp(pname);
std::cout << pname << std::endl;
No, no matter where the trailing 0 of temp is the allocated memory for it is still the initial strlen(Name) + 64 so the delete frees the whole block of memory which is correct.
As #billz pointed out you should not free pname.
No there won't be any memory leak. sprintf will only use the bytes of temp that it requires, BUT, all of the bytes initially created will remain allocated (even though some are unused).
The call to delete[] temp will then deallocate all the bytes originally allocated.
As others have pointed out though, do not free pname. You should only call delete and delete[] on pointers which were created with new and new[] respectively.
Additional information:
When you created temp, new[] allocated an array of contiguous bytes in memory PLUS an additional (small) space where it stores the information about the allocation (how large the allocation is, for instance). When you called delete[] it examined that information and found that strlen(Name)+64 bytes were allocated, and so it knows it has to deallocate all of them. The fact that you only used a small fraction of the allocated space does not make a difference.
Say I create a member variable pointer pBuffer. I send this buffer into some unknown land to be filled with data. Now say pBuffer has an arbitrary amount of data in it.
Q: Is there a way to reset pBuffer without completely deleting it, while still deallocating all unnecessary memory it was occupying?
Example:
class Blah
{
public:
unsigned char* pBuffer;
Blah(){pBuffer = NULL;}
~Blah(){}
FillBuffer()
{
//fill the buffer with data, doesn't matter how
}
ResetBuffer()
{
//????? reset the buffer without deleting it, still deallocate memory ?????
}
};
int main()
{
Blah b;
b.FillBuffer();
b.ResetBuffer();
b.FillBuffer(); //if pBuffer were deleted, this wouldn't work
}
Try realloc() if you know the amount of stuff in the buffer vs the remaining space in the buffer.
Using only a single raw pointer, no; but if you keep a size variable you can reset the buffer relatively easily.
However, this being tagged as C++, I would like to caution you from doing this and will instead propose an alternative. This meets your requirement of allowing memory to be allocated then later for the buffer to be "reset", without deallocating the memory. As a side benefit, using std::vector means that you don't have to worry about the memory leaking in subsequent calls to FillBuffer(), specifically when the existing buffer is too small and would need to be reallocated.
#include <vector>
class Blah
{
public:
std::vector<unsigned char> pBuffer;
Blah(){}
~Blah(){}
FillBuffer()
{
//fill the buffer with data, doesn't matter how
}
ResetBuffer()
{
pBuffer.clear();
// if you _really_ want the memory "pointed to" to be freed to the heap
// use the std::vector<> swap idiom:
// std::vector<unsigned char> empty_vec;
// pBuffer.swap(empty_vec);
}
};
Buffers typically need a maximum size and a current size. To "reset", you would set the current size to zero. When you use it again, you might need to grow or shrink the maximum size of the buffer. Use realloc or malloc/new and memcpy (which realloc does internally when growing) to move existing data to the new buffer.
Note that these are expensive operations. If you expect the buffer to need to grow from use to use, you might consider doubling its maximum size every time. This effectively amortizes the cost of the allocation and copy.
If I declare a data structure globally in a C++ application , does it consume stack memory or heap memory ?
For eg
struct AAA
{
.../.../.
../../..
}arr[59652323];
Since I wasn't satisfied with the answers, and hope that the sameer karjatkar wants to learn more than just a simple yes/no answer, here you go.
Typically a process has 5 different areas of memory allocated
Code - text segment
Initialized data – data segment
Uninitialized data – bss segment
Heap
Stack
If you really want to learn what is saved where then read and bookmark these:
COMPILER, ASSEMBLER, LINKER AND LOADER: A BRIEF STORY (look at Table w.5)
Anatomy of a Program in Memory
The problem here is the question. Let's assume you've got a tiny C(++ as well, they handle this the same way) program like this:
/* my.c */
char * str = "Your dog has fleas."; /* 1 */
char * buf0 ; /* 2 */
int main(){
char * str2 = "Don't make fun of my dog." ; /* 3 */
static char * str3 = str; /* 4 */
char * buf1 ; /* 5 */
buf0 = malloc(BUFSIZ); /* 6 */
buf1 = malloc(BUFSIZ); /* 7 */
return 0;
}
This is neither allocated on the stack NOR on the heap. Instead, it's allocated as static data, and put into its own memory segment on most modern machines. The actual string is also being allocated as static data and put into a read-only segment in right-thinking machines.
is simply a static allocated pointer; room for one address, in static data.
has the pointer allocated on the stack and will be effectively deallocated when main returns. The string, since it's a constant, is allocated in static data space along with the other strings.
is actually allocated exactly like at 2. The static keyword tells you that it's not to be allocated on the stack.
...but buf1 is on the stack, and
... the malloc'ed buffer space is on the heap.
And by the way., kids don't try this at home. malloc has a return value of interest; you should always check the return value.
For example:
char * bfr;
if((bfr = malloc(SIZE)) == NULL){
/* malloc failed OMG */
exit(-1);
}
Usually it consumes neither. It tries to allocate them in a memory segment which is likely to remain constant-size for the program execution. It might be bss, stack, heap or data.
Neither. It is .data section.
Global memory is pre-allocated in a fixed memory block, or on the heap, depending on how it is allocated by your application:
byte x[10]; // pre-allocated by the compiler in some fixed memory block
byte *y
main()
{
y = malloc(10); // allocated on the heap
}
EDIT:
The question is confusing: If I allocate a data structure globally in a C++ application , does it consume stack memory or heap memory ?
"allocate"? That could mean many things, including calling malloc(). It would have been different if the question was "if I declare and initialize a data structure globally".
Many years ago, when CPUs were still using 64K segments, some compilers were smart enough to dynamically allocate memory from the heap instead of reserving a block in the .data segment (because of limitations in the memory architecture).
I guess I'm just too old....
Neither declaring a data structure globally in a C++ consumes heap or stack memory. Actually, global variables are typically allocated in a data segment whose size remains unchanged during the whole program. Stacks and heaps are typically used for variables that get created and destroyed during executing the program.
The global object itself will take up memory that the runtime or compiler reserves for it before main is executed, this is not a variable runtime cost so neither stack nor heap.
If the ctor of the object allocates memory it will be in the heap, and any subsequent allocations by the object will be heap allocations.
It depends on the exact nature of the global object, if it's a pointer or the whole object itself that is global.
global variables live on the heap. these are a special case because they live for the life of the program
If you are explicitly allocating the memory yourself by new or malloc, then it will be allocated in heap. If the compiler is allocating the memory, then it will be allocated on stack.