Clearing stack memory allocated in main()? - c++

I've been calling heap pointers now for as long as I can remember, which in turn has caused me to think about their implications while writing and what I realised was I have no knowledge on how or even if it is possible to clear a stack variable declared within main() from memory once it has been allocated.
Clearly I can just use a struct and destructor or similar, which I would but lets for say I wanted to remove an array that was on the stack declared in main() is it possible?

I wanted to remove an array that was on the stack declared in main()
is it possible?
Yes.
In main() (and most anywhere you use an automatic variable), you can trigger a dtor by closing the containing scope.
Example:
int main(int argc, char* argv[])
{
int retVal = 0;
int arr[10];
T610_t t610;
retVal = t610.exec(argc, argv);
// ...
// ... // t610 exists to end of main() scope.
// ... // arr[10] exists to end of main() scope
return retVal;
}
Instance t610 (of the user defined T610_t type) lasts the life-time of the program, even when not used after the exec() returns retVal;
In contrast:
int main(int argc, char* argv[])
{
int retVal = 0;
{
int arr[10];
T610_t t610;
retVal = t610.exec(argc, argv);
}
// ... // no t610 instance exists, and arr[] is no longer accessible
// ...
// ...
// ...
return retVal;
}
The dtor of instance t610 is called at the close-brace after exec() returns retVal. arr[10] also no longer exists.
All the lines after the close brace do not have access to T610_t, nor arr[10], and any automatic memory grabbed in the 'small scope' is 'released' for re-use. (for instance, another T610_t instance...)
Any 'clearing' of the space used by T610_t is dependent on what the dtor does and what you mean by clearing. Thus, for instance, an array data attribute of T610_t can be filled with 0's (to 'clear' it), and the dtor also releases the memory for re-use. Remember, do no delete when you did no 'new'.

No, you can't really remove a variable out of the current, local scope.
It's not something you should be concerned with - the compiler takes care of everything there.
If you are concerned about privacy, you can of course blank the variable out after use.

A semi-answer to demonstrate a trick the actual answers neglected. (Edit: Neglect changed by the time this was posted)
If you have a large block of memory that you allocated on the stack (an Automatic allocation) and you need that memory back without returning from the function, you can introduce a new scope by calling another function
int get_and_compute()
{
int array[1024*1024];
read_in_a_lot_of_inputs(array);
return compute_stuff_with__array(array);
}
int main()
{
int result = get_and_compute();
// now you have enough memory to call
job_that_takes_a_lot_of_RAM(result);
}
Or by surrounding the code in question with a set of braces
int main()
{
int result = 0;
{ //introduce a new scope
int array[1024*1024];
read_in_a_lot_of_inputs(array);
result = compute_stuff_with__array(array);
} // array goes out of scope here
// now you have enough memory to call
job_that_takes_a_lot_of_RAM(result);
}
Most of the time I prefer option 1, adding a function, but there are times where the extra function doesn't make much sense. Pick the option that is easiest to read, write, and maintain.

I wanted to remove an array that was on the stack declared in main() is it possible?
Simply let the execution go out of the scope where the automatic variable is declared:
int main() {
{
int arr[10];
}
// arr is destroyed, and further local variables can reuse its memory
}

Related

C++ static array in method

One can use static array in method for performance if the method frequently called like
static char [1024];
What I want to ask is , if the array size is small like 128 or 64 which one is more advantageous from the samples one and two.
Sample 1:
void foo(){
static mArr char[128];
memset(mArr,0x0,128);//not sure if this line is necessary but I think its a must , any commends appriciated.
}
Sample 2:
void foo(){
char mArr[128];
}
Sample 3:
void foo() {
char mArr[128] = {0};
}
Little actual difference, the latter basicly just adds 128 to the stack-pointer.
if you only must do the clearing at first run, there can be a saving in:
static char mArr[128] = {0} ;
the memset is only necessary if the array is need to be zeroed-out every time, there's nothing 'magic' with static;
Version 1:
void foo() {
static char a[128];
memset(a,0x0,128);
// use a
}
Allocates a on the heap and provides memory which is persistent over all function calls. a works a bit like a global variable with all the problems of global variables. For example, this version will be problematic if the function is called from multiple threads.
Version 2:
void foo() {
char a[128] = {0};
// use a
}
Allocates a on the stack each time the function is called. ={0} initializes with 0 ( every time the function is called). Use this if you do not need the memory to be persistent over several function calls.
Definitely sample 2 - sample 1 would not compile (first char, then variable name ;)
Anyway, static means the array is set on a fixed position in memory while in sample 2 the array is put on the stack. This is not about advantageous - it's about what you need.
Use 1) if you want to call foo more than once and you always want to use the same array and it should keep it's contents between the calls (without the memset).
Use 2) if you want to use the array just in this function and have a "fresh" array every time you call it.
You do not need the memset - it would just clear the array every time you call foo. While that may be a good thing, it definitely is pointless in combination with static, except you do:
void foo()
{
static mArr char[128];
static bool firstrun = true;
if(firstrun)
{
memset(mArr,0x0,128);
firstrun = false;
}
}
In this case, firstrun would be used to initialize your function at the first run and leave it as is in the following runs.
For using "static" have a look at this article.
I would choose Sample 1 but you maybe need to reconsider memset.
Lets review these senarios:
a) You need to empty the array each time foo() is called.
b) You do not need to empty the array each time foo() is called.
For a:
void foo()
{
char mArr[128] = {0};
}
For b:
void foo()
{
static mArr[128] = {0};
}

Requirement of invoking the clear() function on map variable in C++

By default the program runs fine, but should I explicitly invoke h.clear() in the main(), or is clear() always invoked in case of declaration of a global map variable?
map <int , long long> h;
long long f(int n)
{
.
.
.
}
int main()
{
long long int t,n,x;
//Should I explicitly invoke h.clear() here?
}
clear() is not called for you, but there is no need to. The destructor will take care of cleanup and release the memory used by the map internally.
You should only clear the map if you expect that other global objects which will be destructed upon exiting main depend on fact that the map is empty (which looks like a bad idea, but who knows...)
If your code is really just this, then the map will be empty.
It could be non-empty in more exotic cases like
map <int , long long> h;
int fetchSomeVar()
{
h[ 0 ] = 0;
return 0;
}
int someVar = fetchSomeVar();
int main()
{
//...
}
where fetchSomeVar will be called before main and happens to modify the map, but such constructs should be avoided.
The map will be destructed, but not until after main has finished. Invoking clear() at the end of main or not will only affect your program if h is referenced by destructors of other globals (which ought to be in the same translation unit).

Where to allocate one time use class?

Lets consider the following code:
void main(int argc, char* argv[])
{
Foo foo;
//at this point I don't need foo any more
//a lot of stuff here
}
If I only need foo only for short amount of time,isn't it would be better to allocate it on a heap and delete before executing rest of the code?
No, it's better to write an inner scope.
int main()
{
{
Foo foo;
// use foo
}
// more code
}
But doing this should be a hint that it might be better to put foo in a completely separate function.
There's no reason to use heap allocation here though. That solution would be worse than the problem.

why this access violation

I am getting access violation error in the below code..i have pointed it out in the program.
void *pBuff = 0;
void set_data(void *pBuff)
{
int value = 70, i;
int *phy_bn = new int[8];
for(i=0; i<8; i++)phy_bn[i] = value;
pBuff =phy_bn;
cout<<((int*)pBuff)[0];//..accessing 0th element value..no error here..gives 70 as result..
}
int main()
{
set_data(pBuff);
cout<<((int*)pBuff)[0];//acces violation error
return 0;
}
Why that access violation even when i am not assigning it the address of a local variable...
Yes i can use vector or pass by reference.
But i want to know why pBuff is not getting assigned
Because it is a copy of the pointer being modified within set_data(). Pass the pointer by reference so the change is visible to the caller:
void set_data(void*& pBuff)
Note that the function variable pBuff hides the global variable pBuff in the function set_data().
That said, I am unsure of the reason for void* and why vector<int> is not being used which handles all dynamic memory allocation for you.
When you say
pBuff = phy_bn;
You're just changing the local value of pBuff, not the global value of pBuff. Either pass pBuff as a double pointer, or simply remove the argument to the function, as pBuff is global already.
void *pBuff = 0; /* This is the global pBuff, which isn't being changed */
void set_data(void *pBuff /* This is the local pBuff, which is being changed */)
{
...
pBuff = phy_bn;
...
}
'plz i want to avoid double pointers..its not required i guess...'
Guessed wrong, it is required! You'll need a pointer reference for the pBuff parameter then:
void set_data(void*& pBuff)
{
// ...
}
This is effectively the same as using a double pointer.
The only thing you're doing with
pBuff =phy_bn;
is manipulating the function parameter representation on the local stack.
The pBuff inside set_data is not the global pBuff. The value of the global pBuff never gets changed from 0. Since this is C++ code, set_data can take its pointer argument by reference, and assigning to it will change the value at the point of the function call.
In C++, pointers are passed by value, the same as other value types. It may be instructional to think of a pointer as literally an integer type; then it’s easy to see why pBuff = phy_bn; doesn’t accomplish anything, for the same reason that this code doesn’t:
#include <iostream>
void set(int x) {
x = 5;
}
int main(int argc, char** argv) {
int y = 0;
set(y);
std::cout << y << '\n';
return 0;
}
Here, x is a local variable. It is a copy of y, not y itself. You can change its value by assigning to it, sure, but you’re merely changing the value of a variable which will not exist outside the scope of set(). If you change the definition of set() to use a reference:
void set(int& x) {
x = 5;
}
Then y will indeed be updated, because you have explicitly requested that x be an alias for the name you pass to set(), instead of a copy. You were misled by the names: the pBuf in set_data() is not the same variable pBuf in main(), even though they happen to have the same value; they’re like two different people with the same name and the same amount of money.

How can I get a block of memory from a function and write it to a file?

I want to write the data "somebytes" that I get from a function called NextUnit() to a file named "output.txt", but the code that I wrote does not work. When I open the file, it does not look like my "somebytes". Here is the code:
#include <stdio.h>
#include <string.h>
char* NextUnit()
{
char Unit[256];
strcpy(Unit,"somebytes");
return &Unit[0];
}
int main()
{
FILE *ourfile;
ourfile=fopen("output.txt","wb");
char* somedata;
somedata=NextUnit();
printf("%s\n",somedata);
fwrite(somedata,1,strlen(somedata),ourfile);
fclose(ourfile);
}
You are returning the local address from a function (aka released stack address). Which is then changed once you call the next function.
Ether just return a global constant
const char* NextUnit() { return "somebytes"; }
or copy it into a new memory structure, which you will then need to also free later...
char* NextUnit()
{
char* newstr = new char[256];
strcpy(newstr,"somebytes");
return newstr;
}
// some code later
char* tmpstr = NextUnit();
// do writing stuff
// free memory
delete tmpstr;
You've declared Unit[256] on the stack in a subprocedure. But when your NextUnit() returns, the variable that was scoped to it goes out of scope, and you are no longer pointing to valid memory.
Consider allocating the memory with new, and then releasing it in the caller, or having the caller pass down a pointer to preallocated memory.
you are returning the local address of
a function. Ether just return
const char* NextUnit() { return
"somebytes"; }
so it's constant, or copy it into a
new memory stucture, which you will
then need to also free later...
I don't have enough mojo to comment on the quoted answer, so I have to put this as a new answer.
His answer is trying to say the right thing, but it came out wrong.
Your code is returning the address of a local variable inside the NextUnit() function. Don't do that. Its bad. Do what he suggested.
If you are using C++, the following is a much better way to go about this:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char ** argv)
{
ofstream outFile;
outFile.open("output.txt");
outFile << "someBytes";
outFile.close();
return 0;
}
And, once you are comfortable with that, the next thing to learn about is RAII.
I would rewrite it like this:
char *NextUnit(char *src)
{
strcpy(src, "somebytes");
return src;
}
This way you can decide what to do with the variable outside the function implementation:
char Unit[256];
char *somedata = NextUnit(Unit);
NextUnit returns the address of Unit, which is an array local to that function. That means that it is allocated on the stack, and "released" when the function returns, making the return value non-valid.
To solve this problem you can:
Dynamically allocate a new string each time NextUnit is called. Note that in that case you will have to delete the memory afterwards.
Create a global string. That's fine for a small "test" application, but generally use of global variables is discouraged.
Have main allocate a string (either dynamically or on the stack), pass it as a parameter to NextUnit, and have NextUnit copy to that string.
You have a few problems here. The main one, I think, is that NextUnit() is allocating the buffer on the stack and you're effectively going out of scope when you try to return the address.
You can fix this in a C-style solution by mallocing space for the buffer and returning the pointer that malloc returns.
I think a first step might be to rewrite the code to something more like the following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* NextUnit()
{
char *Unit = (char *)malloc( 256 );
memset(Unit, 0, sizeof(Unit));
strcpy(Unit,"somebytes");
return Unit;
}
int main()
{
FILE *ourfile;
ourfile=fopen("output.txt","wb");
char* somedata;
somedata=NextUnit();
printf("%s\n",somedata);
//fwrite(somedata,1,strlen(somedata),ourfile);
fprintf(ourfile, somedata);
free(somedata);
fclose(ourfile);
}
"Unit" declared as a local variable inside NextUnit which is actually a "stack" variable meaning that it's lifetime is only as long as NextUnit hasn't returned.
So, while NextUnit hasn't returned yet, copying "somebytes" to it is ok, as is printing it out. As soon as NextUnit returns, Unit is released from the stack and the pointer somedata in main will not be pointing to something valid.
Here is quick fix. I still don't recommend writing programs this way this way, but it's the least changes.
#include <stdio.h>
#include <string.h>
char Unit[256];
char* NextUnit()
{
strcpy(Unit,"somebytes");
return &Unit[0];
}
int main()
{
FILE *ourfile;
ourfile=fopen("output.txt","wb");
char* somedata;
somedata=NextUnit();
printf("%s\n",somedata);
fwrite(somedata,1,strlen(somedata),ourfile);
fclose(ourfile);
}
That works but it's kindof pointless returning the address of Unit when it's actually Global!
Declare Unit as static:
char* NextUnit()
{
static char Unit[256];
strcpy(Unit,"somebytes");
return &Unit[0];
}
But if you use C++ compiler you should consider using std::string instead of char*. std::string is more safe and will do all allocation/deallocation jobs for you.