-1

I have some doubts about C allocations.

#include <stdlib.h>

typedef struct MyStruct {
    char CharsInMyStruct[50];
} MyStruct;

int main(void) {

    struct MyStruct * s;

    s = malloc(100 * sizeof *s);
}

I was told that the allocation is "smart", because the space is not "really" (physically) allocated until I use the memory. Is the memory physically allocated once I use the first element of MyStruct or it's allocated when I use each element?

I thought that if I need to dynamically read a file and copy each row in a dynamic struct, I could just allocate for 100 elements, then realloc for the correct dimension after reading the file, so I don't have to read two times to previously know how much to allocate or to realloc for each row. Is that possible / allowed? Is it a good solution?

Edit: sorry, I was too concerned about theory and I forgot to add a decent code. Maybe the question is not clear enough, but I don't need to know how to code what I'm thinking about; I just need to know how the memory is allocated.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user3574984
  • 453
  • 2
  • 6
  • 16
  • 1
    Your code should not even compile. And you should show us what `MyStruct` is. And probably use `sizeof(MyStruct)` inside `malloc` call. **Show us your actual code**; in general C or its allocation is not smart. – Basile Starynkevitch Jul 26 '14 at 01:37
  • 1
    Also [don't cast the result of malloc in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – BlackDwarf Jul 26 '14 at 01:39
  • Your code snippet is strange (won't compile, unclear what it really is supposed to do). It doesn't help to make your question clearer, rather it does the opposite. You should explain what the code snippet is supposed to illustrate/..., at the moment it's mostly confusing. – sth Jul 26 '14 at 01:41
  • I didn't post the code because I thought the rest of the code (read function, realloc function, copy of the elements in the struct, etc) wasn't relevant for the question. I wanted to know how does the memory allocation works on a lower level, I don't have trouble with the code itself! – user3574984 Jul 26 '14 at 01:47
  • `struct MyStruct *var; var = malloc(sizeof(struct MyStruct) * 100);` – BLUEPIXY Jul 26 '14 at 01:58
  • I know you're not asking about the code you posted, but ... `void Main()` needs to be `int main(void)`, the allocation is better written as `s = malloc(100 * sizeof *s);`, and you need `#include ` at the top of the source file. – Keith Thompson Jul 26 '14 at 02:04

4 Answers4

3

In principle, calling malloc() causes the requested memory to be allocated immediately. If it's unable to do so, the malloc() call returns a null pointer to let the caller know.

In practice, though some systems (including Linux) use "lazy allocation". The malloc() call immediately allocates a range of memory addresses, but doesn't necessarily allocate the actual memory pages right away. When your program later accesses the "allocated" memory, physical memory is allocated by the kernel. The idea is to avoid allocating memory that might never be used, particularly when forking processes (a child process inherits a copy of its parent's memory, but typically exec()s another executable before using it.)

One big drawback of this approach is that if the memory isn't available when you try to use it, there's no clean way to report the failure. When the system is short on memory, the "OOM killer" may start killing processes -- not necessarily the one that performed the allocation.

It's been argued that this behavior causes C implementations on Linux to be non-conforming.

I'm less familiar with non-Linux systems.

For most practical purposes, though, as long as you're not allocating huge amounts of memory, you can probably ignore all this. You should always check whether malloc() reported failure by returning a null pointer, and take some action (even if you just terminate your program). If you do a large malloc in an infinite loop, bad things are likely to happen. But when resources are in short supply for whatever reason, programs are likely to start crashing anyway. Your best defense is to design your program so it doesn't leave things in an inconsistent state if it terminates unexpectedly.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Memory overcommitment can be disabled on Linux thru `/proc/sys/vm/overcommit_memory` – Basile Starynkevitch Jul 26 '14 at 02:27
  • Thank you Keith, but is the memory allocated all at once? In my case, if I use the first element, linux allocates memory for 100 structs or only for one? – user3574984 Jul 26 '14 at 02:29
  • @user3574984: As far as I know, memory is allocated in pages. I don't know how big a "page" is; it may vary from one system to another. For your example, 100 `struct MyStruct` objects is about 5000 bytes, which is tiny, but if the OS uses, say, 4096-byte pages, it might allocate just one page when you access the first element. (Again, as far as the C language standard is concerned, it's all allocated when you call `malloc()`. To some extent it depends on just what "allocated" really means.) – Keith Thompson Jul 26 '14 at 02:50
1

As comment said:

struct myStruct * structLink;
structLink = malloc (sizeof(struct myStruct));

Also when finished:

free(structLink);

To deallocate.

fingaz
  • 241
  • 1
  • 6
  • I'll try to reformulate my question: if I allocate for 100 structs, is the memory physically allocated in the declaration or the effective allocation happens when I use the StructLink for the first time? – user3574984 Jul 26 '14 at 02:04
  • I would believe once using malloc that the memory is allocated. To test this though, use the malloc command and try printing the memory address of structLink. Then, utilize structLink and print the address again. That might clear things up for you! – fingaz Jul 26 '14 at 02:12
1

As others have said, logically malloc() allocates the space and it is available for use immediately. As Keith Thompson noted in his answer, Linux takes a lazy approach to memory allocation, so you can (if you're unlucky) allocate space, check that it was allocated, and yet still crash later because the memory wasn't available after all.

  1. Yes, it is legitimate to allocate 100 entries, read from a file to populate some of those entries, and then realloc() to shrink the array to the required size if there are fewer than 100 entries after all.

  2. You can also allocate an array of entries (say 2 entries to start with), and realloc() the space to add more entries as required. However, to avoid quadratic behaviour (copying the old space to new space), the standard advice is to double the number of entries each time you realloc(). You can always apply the shrinking realloc() after the loop if you're worried about over-allocation. Use a small value to start with so that the realloc() code does get exercised (tested, debugged).

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thank you for the exhaustive answer. Even if it's legit the allocation then the reallocation, is it considered safe for a program or I should find another way to solve the problem? Dynamically allocate like this is a bad habit? – user3574984 Jul 26 '14 at 02:38
  • It is safe and kosher and reliable and sensible, especially if your previous allocation was for 4 million entries and it turns out that there were only 2 million and ten entries in the file; you might well have a use for almost 2 million array entries. – Jonathan Leffler Jul 26 '14 at 02:40
1

I think you may have your thoughts on memory usage wrong. When you allocate memory, the memory is always there to begin with, malloc just tells the computer to reserve this much space for you. When you use free() after you're done, the pointer that you freed will still be pointing to that address. The only difference is that the program will know it's not your space to use anymore. ( Though C will probably still allow you until you get a segment fault )

As for your second paragraph, the way you do it depends upon implementation. Though really I don't see why you cannot just malloc on the go every time you read in a new file.

Pardon if this isn't what you're looking for.

Dacer
  • 7
  • 2
  • because I have to read a file with n rows, each with x characters. I would like to copy each row in structs, but I want allocate the exact space for each row, so I use a pointer to char. So I open the file, I copy the content in a static char array (around 2k elements), than I copy each row in a struct. My problem is that I would like to know how many rows or how many char for each row without reading the file twice. I'm not sure it's clear enought. – user3574984 Jul 26 '14 at 11:47