LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   global declaration is in stack or in heap? (https://www.linuxquestions.org/questions/programming-9/global-declaration-is-in-stack-or-in-heap-4175557950/)

savio 11-04-2015 06:32 AM

global declaration is in stack or in heap?
 
I need to declare a variable that is not in the stack memory but in the heap, like below

Code:

struct mystruct *name;
Should I declare it outside all functions (even outside main()) at the begin of file?

NevemTeve 11-04-2015 06:56 AM

If you put this line into a function, it will be an uninitalized pointer, that exists on the stack.

If you put this line outside any function, it will be an NULL-initalized pointer, a global variable (neither heap or stack)

savio 11-04-2015 07:54 AM

I just made two examples:

Code:

#include <stdio.h>

struct record {
  int elem;
  char c;
} myrecord;

int main(int argc, char** argv) {

  struct myrecord *r;

  printf("myrecord *r = %p\n", r);

  return 0;

}

and

Code:

#include <stdio.h>

struct record {
  int elem;
  char c;
} myrecord;

struct myrecord *r;

int main(int argc, char** argv) {

  printf("myrecord *r = %p\n", r);

  return 0;

}

I use MAC OS X and the output is the same:

Code:

myrecord *r = 0x0
that is NULL.

psionl0 11-04-2015 08:36 AM

Quote:

Originally Posted by savio (Post 5444476)
I need to declare a variable that is not in the stack memory but in the heap, like below

Code:

struct mystruct *name;
Should I declare it outside all functions (even outside main()) at the begin of file?

Heap memory is used when you use malloc as in
Code:

name = malloc(sizeof(struct mystruct));
if you don't wan't a variable to be on the stack then you could preface its declaration with static but then the same variable will used everytime the function is run so recursion might not be practicable.

Declaring variables outside of any function will make them global and they should not be created on the stack (but I'm not sure if that is a rule).

In your two examples, r exists on the stack in the first example and globally in the second. Note that you have not initialized r (with malloc) yet so the value of r (and therefore what it points to) is indeterminate.

NevemTeve 11-04-2015 08:54 AM

> I just made two examples:
> I use MAC OS X and the output is the same:
> that is NULL.

That's cool. Only remember that the first one isn't guaranteed to be always NULL; actually, it is memory-garbage that happened to be NULL in this example.

sundialsvcs 11-04-2015 11:25 AM

Any variable that is declared within the body of a function is "local" to that function. It exists only when the function-instance does [i](recursive functions have a copy for each instance), and its lexical scope is such that only code within the body of the function can "see it" to refer to it.

Any variable that is declared outside the scope of all functions is global and can be accessed by any function.

The "C" language does not provide for variable-initializers. You should assume that the value of all variables is "unpredictable."

bigearsbilly 11-06-2015 02:37 AM

static and global variables are initialised to null in C.

wroom 11-06-2015 12:36 PM

Quote:

Originally Posted by bigearsbilly (Post 5445458)
static and global variables are initialised to null in C.

Yes.

Exception being if the linker has a manipulated map file, and/or the process initializer code is customized not to initialize globals. Which really only happens in embedded programming.

It is a good rule to always initialize variables to a known state. global/static or local.

About memory returned by malloc. A decent desktop OS will always wipe that memory before given to the process asking for memory. Therefore it will very often be wiped to zero.

BUT. If a process first malloc a block of memory, and then frees the same block, and then after that mallocs another block of the same size - Chances are that the process hasn't yet released that block of memory to the system garbage collection. So the newly malloced block of memory could still have the contents retained from the previous malloc.

In the VMS operating system the system manager can on the fly set how memory pages are wiped or not. It can be set to any combination of: Wipe at allocation, or not. Wipe when freed, or not. and cyclic scrubbing of available memory, (or no scrubbing), when returning "dirty pages" to be free pages available for allocation.

So the rule is: Always initialize variables and allocated memory.

Example of clearing a struct bios_geometry_t of potentially undefined size, pointed to by the first member '0' of the array 'fr' of struct, specifically it's struct member 'BiosGeom':
Code:

memset(&(fr[0].BiosGeom),0,sizeof(struct bios_geometry_t));
Or the simpler example to allocate an array of 99 unsigned elements, all initialized to 0:
Code:

unsigned * x;
x = malloc(sizeof(unsigned)*99);
if (x == 0) abort();
memset(x,0,sizeof(unsigned)*99);


NevemTeve 11-06-2015 01:08 PM

Or, two more options:
Code:

uptr = calloc (sizeof (unsigned), 99);
uptr = calloc (sizeof *uptr, 99);


sundialsvcs 11-06-2015 07:29 PM

Upon re-reading, I realize that I slightly-misspoke.

There are three memory areas that a program can use:
  1. the "BSS" area ...
  2. The "stack." And ...
  3. The "heap."

When a program starts, a certain portion of the data-segment is allocated for "statically-allocated, 'global,' variables," which includes all variables that are declared outside of any function. All such variables are each bound to one, unchanging memory-address within this space.

Another area of memory, usually referenced by a separate processor "stack segment" register, is used to handle subroutine calls. Any memory needed by an executing subroutine/function for its "local" variables is only needed while that particular function-call instance exists, after which it can be re-used, therefore a "push-down stack" paradigm is used to manage it. (This also supports recursion, in which a subroutine/function can safely call itself, without conflict.) The stack area grows and possibly shrinks as required.

The third and final area of memory ... unrelated to the other two ... is called "the heap." This space is used to satisfy requests for memory that are made ad hoc by the running program itself. (The term, "heap," is meant to represent the fact that this memory area has no pre-determined structure or organization of its own.) When a program determines that it needs some amount of memory, it asks for it (malloc()), and, when it decides that it no longer needs some piece, it returns it (free()).

Since it is, of course, impossible to know just where the requested memory-block (in "the heap") might be, pointers are always used to refer to these areas ... indirectly.

A pointer, physically speaking, is merely an integer value of some certain width whose contents are understood to represent a memory-address. ("Zero" has the special meaning, NULL.) The term refers to the fact that, while the particular (integer ...) value of the pointer is uninteresting, the data at that location ("what the pointer 'points to' ...") is.

Pointers, being "merely high-falutin' integers," can be stored anywhere: in the BSS area, in a stack ("local") variable, or in the case of so-called "linked lists" and other "data structures," elsewhere in the heap.

wroom 11-06-2015 09:02 PM

Quote:

Originally Posted by savio (Post 5444476)
I need to declare a variable that is not in the stack memory but in the heap, ...
Should I declare it outside all functions (even outside main()) at the begin of file?

Reviewing the initial question, i give the following "short" answer:

Either declare the variable globally, outside all functions. Or declare the variable inside a function, but use a 'static' declaration, which will give the variable the same allocation as for the global variables, with the exception that the variable is only visible inside that function.

Being a static variable makes it allocated such that its contents are preserved between different serial invocations of the function. Best practice is still to reinitialize the variable everytime the function is invoked, and not use the side effect of the static variable preserving its content. (The exception being the static members of an object/class instantiation in C++).
Use global static variables to preserve data between function invocations. Not the function local static variables.

Please be aware that a static declared variable in a function will make that function non-reentrant, and that function may not be used in multithreaded applications without a locking mechanism preventing simultaneous execuion of the non-reentrant function. Also note that such a static variable can be pointed to by a function returning a pointer to the contents, and that another invocation of that function will overwrite the contents of the pointed out return data. Thus, non-reentrant.

Another concept that provides a form of static allocation that can be reentrant is the use of "workspaces" allocated in some form of block pool handler. Simplest implementation of this may well be allocation of "new objects of a class" in C++, each getting it's own separate workspace allocated in heap when instantiated, and as such capable of running multithreaded in the form of "one object per thread". But the functions of such an object are still not reentrant.

For realtime performance, and also for reliable execution, the concept of avoiding dynamic allocation is essential. Global and static allocation is enforced, and dynamic allocation kept to an absolute minimum.
Having lots of small functions that allocate large arrays/buffers dynamically, for a short time, either on stack or in paged memory, are detrimental to reliable, predictable realtime performance.

NevemTeve 11-06-2015 11:34 PM

I guess the OP wanted to know whether definition a pointer also defines an object of the pointed type [no], and where that object will reside [nowhere].

sundialsvcs 11-07-2015 09:50 AM

Probably.

And, whenever possible, I now strongly recommend that people write "new stuff" in a higher-level language, even "C++," which does possess built-in support for "real strings," container classes that "just work," and so-forth. You're leveraging a much more expressive source-code language that already knows how to "do the right thing for you" in many useful cases.

The "C" language is, in a very real sense, just a very small step-up from assembly language ... and-d-d-d, it was designed so to be! But, when you write code in it, you're obliged to concern yourself, all over again, with a bunch of niggling things that ought not have to concern you. You're opening yourself up to "more ways that you can possibly screw-up" :) than you need to. (Given that you are, of course, "going to screw up," make the screw-ups interesting, not mundane.)

NevemTeve 11-07-2015 12:15 PM

Yes, C++ is very good for beginners. Details here: http://yosefk.com/c++fqa/

psionl0 11-08-2015 02:07 AM

Quote:

Originally Posted by wroom (Post 5445839)
Use global static variables to preserve data between function invocations. Not the function local static variables.

Better still, any variables that need to be conserved between function invocations should be stored by the calling function and a pointer passed to those functions that need it. The use of global variables is generally not good programming practice because of portability issues and the difficult to find bugs it can cause.

Quote:

Originally Posted by wroom (Post 5445839)
Please be aware that a static declared variable in a function will make that function non-reentrant,

... but not necessarily non-recursive. As long as the value of the static variable prior to the latest invocation of the function can be computed, recursion is still possible. (In my BASIC programming days, this was the method I used as an alternative to setting up data stacks for recursive subroutining). I agree that there are usually better alternatives to local static variables (other than in main()). Of course, if re-entrancy is not an issue then the point is moot.

Quote:

Originally Posted by wroom (Post 5445839)
For realtime performance, and also for reliable execution, the concept of avoiding dynamic allocation is essential. Global and static allocation is enforced, and dynamic allocation kept to an absolute minimum.
Having lots of small functions that allocate large arrays/buffers dynamically, for a short time, either on stack or in paged memory, are detrimental to reliable, predictable realtime performance.

I have never heard of this rule of thumb before. Is this because of the way Linux allocates memory? There are many cases where the amount of memory required can not be known beforehand and dynamic allocation is the only way around this. In some languages (like Java), every non-elemental variable has to be dynamically allocated.


All times are GMT -5. The time now is 02:51 AM.