-3

I want to move on from writing small one/two/three-filed C programs to slightly larger C projects. For that I really want to get the memory management right. Now I know that similar questions have been asked, but they won't quite answer mine. I know some of the theory already and put it to use. Therefore I'd like to present what I know or think to know and you correct me or add information I miss.

  1. There is the stack, static memory and the heap

    static int n;                               // goes to static memory, thread lifetime
    char *array = malloc(256 * sizeof(*array)); // goes to heap, needs free(array)
    
    func(int n) {
        float f;         // goes to stack, dies with func return
        static double d; // thread lifetime again
    }
    
  2. Static memory can't overflow since it's set for all static variables, however heap and stack can overflow, heap overflows when non allocated memory is accessed in most cases, stack is set to ~1MB Windows or ~8MB Linux, if that is exhausted (I got a message "core dumped" on my Ubuntu for setting up an array of structs for every pixel of an image on the stack)

Does static, stack and heap memory behave like this in every scope? I know heap memory does. But does a global non static array of structs go on the stack? What if I have a static array in file b where there is no main? Goes on to static memory right? And what is if a function has a local static variable with initialized value? Is it initialized everytime i call the function? and do functions take from the stack? How to avoid exhausting the stack in large programs with long lifed stack variables and plenty of them? And most of all, where do string literals go?? They are supposed to be pointers not arrays, but if i change the pointer what happens to the original string? One more thing: It always bothers me how it looks straight up bad practise to write code like

         if(!strcmp(a, "comparethis")) do ...

or

         fprintf(stderr, "There was a problem .... %d", something);

EDIT

Where is the difference in terms of memory management?

         char arr[3] = {'A', 'B', 'C'};
         char arr[3] = "ABC";
         char *arr = "ABC";

EDIT END

Is it good to include string literals anyway or rather read them from a file or whatnot?

Finally, sorry if my grammar failed me here and there but this was written in a fast manner. Thanks for reading and please no hate. Outline my mistakes, don't judge them, if I can ask that much. I wanna improve and fast.

Have a good day anyway.

PenPen
  • 11
  • 3

1 Answers1

2

There is the stack, static memory and the heap

Not exactly. C standard defines automatic storage, static storage and dynamic storage. The stack is a possible (in fact the common) implementation for automatic storage, as is the heap for dynamic storage. This definitions acts on the lifetime of variables:

  • automatic objects have their life bound by their containing block
  • static objects come to life at the beginning of the program, and their life extends to the end of the program
  • dynamic variables are created by malloc (and associated) function(s) from the standard library and shall be destroyed by free.

Provided these rules are obeyed, an implementation if free to physically store objects where it wants to. In particular, some implementations were known to store automatic arrays on the heap and automatically destroy them at block exit

Static memory can't overflow since it's set for all static variables

In the time of MS/DOS, the small memory model required all static variable to fit in a single segment of 64 kbytes. If you wanted more, you could not compile in that mode. The error could be a compile error in one single compilation unit caused the error, or a link error if only the total size exceeded 64k

stack is set to ~1MB Windows or ~8MB Linux

Compiler options allow to change the size of the stack on common compilers

Now for your questions:

does a global non static array of structs go on the stack?

it can depend on implementation, provided it is automatically destroyed when leaving block, it can be stored on the heap

What if I have a static array in file b where there is no main? Goes on to static memory right?

Yes it has to be static, whether the translation unit contains a main or not

And what is if a function has a local static variable with initialized value? Is it initialized everytime i call the function?

as it is static, it is created and initialized at the beginning of the program, and keeps its value through other calls. It is not reinitialized on following calls

and do functions take from the stack?

What do you mean here? Common implementation do use the stack for the function return address and all its automatic variables

How to avoid exhausting the stack in large programs with long lifed stack variables and plenty of them?

You can increase the stack size at compile time, or use a different design. For example iterative algorithms are less stack consuming than recursive ones

And most of all, where do string literals go?

A string litteral has static duration. Some implementation store them in a read only segment, but there is no requirement for it. Simply it is undefined behaviour to try to modify a string litteral.

Where is the difference in terms of memory management?

     char arr[3] = {'A', 'B', 'C'};
     char arr[3] = "ABC";
     char *arr = "ABC";

First and second ones both declare a non const array of 3 characters initialized with A, B and C, and no terminating null.

Third one is quite different: it declares a pointer to a (null terminated) string litteral. That means that arr[0] = 'X'; is undefined behaviour because it modifies a litteral. And sizeof(arr) the length of the string litteral but sizeof(char *).

Is it good to include string literals anyway or rather read them from a file or whatnot?

I cannot understand the question. A string litteral is available inside the program. A string stored in a file requires access to the file. So at least the file name has to be a string litteral.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252