Why do successive calls to new[] not allocate contiguous memory?

Asked
Active3 hr before
Viewed126 times

5 Answers

calls
90%

The memory allocator may "round up" the size of an allocated block to make things easier for it. For instance, an allocation of 7 bytes will likely be rounded up to 8 bytes, if not even 16 or 32., 1 You are not allocating memory directly from the OS. The runtime manages its own heap, which in turn, is allocated from the OS. There is no guarantee that successive calls to new() are contiguous. Never assume that in your code. – OldProgrammer Sep 5 '14 at 2:07 , Also, every time you malloc() memory or new[] an array, the runtime has to add some extra bytes to keep track of how much memory/how many objects were allocated, so when you later free() or delete[] the memory it knows how much to clean up. – Alex MDC Sep 5 '14 at 2:13 ,Blocks of memory may already be available in noncontiguous locations. (Keep in mind that the C runtime may have been making some memory allocations of its own before main() even runs.)

I am using Ubuntu 14.04 64-bit. Here is my C++ code to see how memory is used.

int main() {
   int ** ptr;

   ptr = new int * [2];
   cout << & ptr << " -> " << ptr << endl;

   for (int r = 1; r <= 2; r++) {
      ptr[r - 1] = new int[2 * r];
      cout << & ptr[r - 1] << " -> " << ptr[r - 1] << endl;

      for (int c = 0; c < 2 * r; c++) {
         ptr[r - 1][c] = r * c;
         cout << & ptr[r - 1][c] << " -> " << ptr[r - 1][c] << endl;
      }
   }

   return 0;
}
load more v
88%

Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc(),Since C is a structured language, it has some fixed rules for programming. One of them includes changing the size of an array. An array is a collection of items stored at contiguous memory locations.  ,How to deallocate memory without using free() in C?,Difference Between malloc() and calloc() with Examples

The “malloc” or “memory allocation” method in C is used to dynamically allocate a single large block of memory with the specified size. It returns a pointer of type void which can be cast into a pointer of any form. It doesn’t Iniatialize memory at execution time so that it has initializes each block with the default garbage value initially. 
Syntax: 
 

ptr = (cast - type * ) malloc(byte - size)
For Example:
Output:
Enter number of elements: 5
Memory successfully allocated using malloc.
The elements of the array are: 1, 2, 3, 4, 5,
  1. “calloc” or “contiguous allocation” method in C is used to dynamically allocate the specified number of blocks of memory of the specified type. it is very much similar to malloc() but has two different points and these are:
  2. It initializes each block with a default value ‘0’.
  3. It has two parameters or arguments as compare to malloc().
    Syntax: 
     
ptr = (cast - type * ) calloc(n, element - size);
here, n is the no.of elements and element - size is the size of each element.
Output:
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,

“free” method in C is used to dynamically de-allocate the memory. The memory allocated using functions malloc() and calloc() is not de-allocated on their own. Hence the free() method is used, whenever the dynamic memory allocation takes place. It helps to reduce wastage of memory by freeing it.
Syntax: 
 

free(ptr);
Output:
Enter number of elements: 5
Memory successfully allocated using malloc.
Malloc Memory successfully freed.

Memory successfully allocated using calloc.
Calloc Memory successfully freed.

“realloc” or “re-allocation” method in C is used to dynamically change the memory allocation of a previously allocated memory. In other words, if the memory previously allocated with the help of malloc or calloc is insufficient, realloc can be used to dynamically re-allocate memory. re-allocation of memory maintains the already present value and new blocks will be initialized with the default garbage value.
Syntax: 
 

ptr = realloc(ptr, newSize);

where ptr is reallocated with new size 'newSize'.
Output:
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,

   Enter the new size of the array: 10
Memory successfully re - allocated using realloc.
The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
load more v
72%

Memory for named variables is allocated by the compiler,We can dynamically allocate storage space while the program is running, but we cannot create new variable names "on the fly",It is the programmer's job to deallocate dynamically created space,dynamically allocated space usually placed in a program segment known as the heap or the free store

type
 new int; // dynamically allocates an int 
 new double; // dynamically allocates a double
load more v
65%

However, only the first dimension size can be unspecified in the parameter definition: you need to indicate that the parameter is a 2-D array, and can leave the size of the first dimension unspecified (for good generic design), but the second dimension is needed by the compiler to generate the correct address: , Allocate an array of arrays: allocate 1 array of N pointers to arrays, and allocate N M bucket array of values (on for each row). You could also allocate each column independently and have an array of column arrays. , However, you can use a pointer to point to each bucket value and then increment the pointer to point to the next one. When incremented, a pointer points to the very next storage location of that type (the address the pointer holds is incremented by the size of the type it points to): when incremented an int pointer point points to the very next int storage address (the address 4 bytes beyond the current one); and when incremented a pointer to a char points to the very next char storage address (the address 1 byte beyond the current one). , Information about Statically Allocated Arrays Information about Dynamically Allocated Arrays Information about Dynamically Allocated 2D Arrays

1-D arrays

int a1[100]; // declare a static array, a1, of 100 ints
char c1[50]; // declare a static array, c1, of 50 chars

// accessing array elements using indexing
for (i = 0; i < 100; i++) {
   a1[i] = 0;
}

Array Parameters

// pass in the dimention of the array, n, to make this 
// function work for any size array
void init_array(int arr[], int n) {
   int i;
   for (i = 0; i < n; i++) {
      arr[i] = i;
   }
}

int main() {
      int array[100];

      init_array(array, 100);
      ...

Array Memory Layout

array[0]: base address
array[1]: next address
array[2]: next address
   ......
   array[99]: last address
i * (sizeof(buckettype)) + array_base_addr
addr bucket
-- -- -- -- -- -- --
1230: array[0](base address of array)
1234: array[1]
1238: array[2]
   ......

2-D Arrays

int matrix[50][100]; // declared a static 2D array of 50 rows, 100 cols
 int val = matrix[3][7]; // get int value in row 3, column 7
     0 1 2 3...99
     0:
        1:
        2: x
        .
        .
        .
     49: y

     x is stored at matrix[2][3]
     y is stored at matrix[49][99]
for (i = 0; i < 50; i++) {
   for (j = 0; j < 100; j++) {
      matrix[i][j] = 0;
   }
}

2-D Array Memory Layout

matrix[0][0]: base address
matrix[0][1]: next address
matrix[0][2]: next address
   ......
   matrix[0][99]:
   matrix[1][0]:
   matrix[1][1]:
   ...
   matrix[1][99]:
   matrix[2][0]:
   ...
   matrix[49][0]:
   matrix[49][1]:
   ...
   matrix[49][99]:

However, only the first dimension size can be unspecified in the parameter definition: you need to indicate that the parameter is a 2-D array, and can leave the size of the first dimension unspecified (for good generic design), but the second dimension is needed by the compiler to generate the correct address:

void init_matrix(int m[][100], int rows) {
   int i, j;
   for (i = 0; i < rows; i++) {
      for (j = 0; j < 100; j++) {
         m[i][j] = i * j;
      }
   }
}

int main() {
      int matrix[50][100];
      init_matrix(matrix, 50);

However, you can use a pointer to point to each bucket value and then increment the pointer to point to the next one. When incremented, a pointer points to the very next storage location of that type (the address the pointer holds is incremented by the size of the type it points to): when incremented an int pointer point points to the very next int storage address (the address 4 bytes beyond the current one); and when incremented a pointer to a char points to the very next char storage address (the address 1 byte beyond the current one).

// accessing array elements using pointer arithmetic
char * cptr = NULL;
int * iptr = NULL;

// make the pointer point to the first bucket in the array
// the address of the start of an array is given two ways:
//   &(array[0])  the address of bucket 0 
//   array            also the address of bucket 0 

cptr = & (c1[0]); // initialize cptr to point to the start of c1
iptr = a1; // initialize aptr to point to the start of a1
for (i = 0; i < 50; i++) {
   * cptr = 'a';
   * iptr = i;
   cptr++; // cptr points to the next valid char address (the next bucket of c1)
   iptr++; // iptr points to the next valid int address (the next bucket of a1)
}

// sets first matrix to: 
// row 0:   0,   1,   2, ...,  99 
// row 1: 100, 110, 120, ..., 199
//        ...
iptr = & (matrix[0][0]);
for (i = 0; i < 50 * 100; i++) {
   * iptr = i;
   iptr++;
}
load more v
75%

The code calls operator new[] to allocate memory for 10 string object, then call the default string constructor for each array element.,Uninitialized Memory Since C/C++ allows us to create variables without an initial value, we may try to read data not initialized. The memory allocation function malloc() and operator new do not the allocated memory.,delete ptr - frees the memory for an individual object allocated by new.,It calls a constructor to initialize an object in the memory that was allocated.

Incorrect Memory Management
This can occur when we call free() more than once, access memory after freeing it,
or free a memory block that was never allocated as shown in the code below:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void populate(char **str) {
	// 1. OK
	*str = (char *)malloc(sizeof(char) * 7);
	strcpy(*str, "Memory");

	// 2. Not OK if later freeing the memory
	*str = "Memory";
}

int main() {
	char *s;
	populate(&s;);
	printf("%s", s);   // should print "Memory"
	free(s);
	return 0;
}

load more v

Other "calls-undefined" queries related to "Why do successive calls to new[] not allocate contiguous memory?"