Incorrect 2D array access - c

I've got an unusual condition.
Here's the snippet:
int i, j;
short ** s = (short **)malloc(128);
for(i = 0; i < 14; i++){
s[i] = (short *)malloc(128);
for(j = 0; j < 128; j++)
s[i][j] = 0;
}
printf("Value of s[%d][%d] = %d\n",2,40,s[2][40]);
s[1][108] = 99;
printf("Value of s[%d][%d] = %d\n",2,40,s[2][40]);
The output I get when I run this is:Value of s[2][40] = 0
Value of s[2][40] = 99
Eliminating the loops and writing short s[14][128] yields the correct output (Value of s[2][40] is 0 in both prints)
Why am I able to access s[2][40] with s[1][108]?
I'm using gcc on Ubuntu 12.04.

You are accessing out of bounds of the space you allocated, which causes undefined behaviour.
s[i] = (short *)malloc(128) allocates 128 bytes. But then you try to write 128 shorts to that space. Since shorts are bigger than 1 byte, you run off the end of the allocation.
Also, short ** s = (short **)malloc(128); probably allocates too much space, since you only use 14 rows.
Assuming you want an array of 14 x 128 the way is:
short **s = malloc( 14 * sizeof *s );
for (size_t i = 0; i < 14; ++i)
s[i] = malloc( 128 * sizeof *s[i] );
malloc takes the number of bytes, so you have to multiply the number of elements by the size of each element.
Note that if you do not need the feature of being able to make different rows different sizes then you can allocate it in a single bloc:
short (*s)[128] = malloc( 14 * sizeof *s );
and in both cases you can use s[i][j] the same.
Finally, you should also check that the pointer returned by malloc is not NULL, and also free the pointer after you are finished with the memory.

First it is not a correct way of allocating memory for 2D array-
short ** s = (short **)malloc(128);
for(i = 0; i < 14; i++){
s[i] = (short *)malloc(128);
This is wrong way!
short ** s = (short **)malloc(128);
Here you are allocating memory for array of 128 bytes for short **.
for(i = 0; i < 14; i++){
s[i] = (short *)malloc(128);
But you are using only 14 short *. That is only 28 bytes used(because sizeof(short) = 2).
Why am I able to access s[2][40] with s[1][108]?- Because you are accessing the array out of bounds!
How?
s[i] = (short *)malloc(128);
This will allocate memory for array of 128 bytes for each short *. That means you can store Maximum 64 short elements in Each 1D array.
But you are trying to access s[1][108] - means 108th element in the 1st row of the array. It is Out of bounds for the allocated memory. So you will not get the expected output.
Try to allocate memory like this-
short **s = malloc(sizeof(short *) * 14);
for(i = 0; i < 14; i++){
s[i] = malloc(sizeof(short) * 128);

Related

realloc invalid next size for array

Hello I keep getting invalid next size when using realloc to allocate more memory to an array which im trying to add 100,000 numbers too. I dont know why because im not understanding why it wont work. My code is here below.
int main()
{
printf("starting");
int i;
int *bubbleSortArray = (int *)malloc(sizeof(int));
int numberOfElements = 0;
int randomNumber;
srand(time(NULL));
int j;
for (int j = 0; j <= 100000; j = j +1)
{
randomNumber = rand();
if(numberOfElements != 0)
{
bubbleSortArray = (int *) realloc(bubbleSortArray, numberOfElements * sizeof(int));
}
bubbleSortArray[numberOfElements] = randomNumber;
numberOfElements = numberOfElements + 1;
}
}
In the statement you need to write at least like
bubbleSortArray = (int *) realloc(bubbleSortArray, ( numberOfElements + 1 )* sizeof(int));
Otherwise this statement
bubbleSortArray[numberOfElements] = randomNumber;
invokes undefined behavior.
Also you need to use an intermediate pointer to store the return value of the call of realloc because the function can return a null pointer. In this case the previous value stored in the pointer bubbleSortArray will be lost and you will not have an access to the already allocated memory.
So it would be better to write
int *tmp = (int *) realloc(bubbleSortArray, ( numberOfElements + 1 )* sizeof(int));
if ( tmp != NULL )
{
bubbleSortArray = tmp;
}
else
{
// some other code
}
Pay attention to that these declarations
int i;
int j;
are redundant because the declared variables are not used.
Oh, this is kind of scary. I'm not sure why you're not allocating enough space up front. But this code is going to realloc 100,000 times, which is an insane thing to do. Do you know what realloc does under the hood? I'll explain.
First, it does a NEW alloc of the amount of data. So the first time you loop, numberOfElements is zero, and you use your malloc'd space. But the second time it allocates space for 2 integers, then 3 integers, then 4, et cetera.
So it allocates 8 bytes. It remembers how much it allocated last time (4 bytes -- the size of an int on most systems), and it then does a memcpy of that much space.
Then it memcpy's 8 bytes. then it memcpy's 12 bytes, and so on and so on.
Bad, bad, bad.
What most people do is keep track of two values -- the amount of space allocated (capacity) and the amount used (count or numberOfElements).
So it looks something like this:
int capacity = 16;
int *bubbleSortArray = (int *)malloc(capacity * sizeof(int));
...
if (numberOfElements >= capacity) {
// Increase capacity by whatever means you want.
// You can double it. Or you can:
capacity += 16;
bubbleSortArray = (int *) realloc(bubbleSortArray, capacity * sizeof(int));
}
Ah, and as I cut & pasted your code, I see that you used numberOfElements. So you were consistently undersizing your realloc by 1, anyway.

All elements in array being set to last element in C?

sorry if this is a stupid question but I'm having an issue where all the elements of my array are being set to the last element in C. I think I'm overriding something and would like another pair of eyes. My goal is create an array of random numbers of type char. Code is below:
int main(int argc, char *argv[]) {
unsigned int seed = atoi(argv[1]);
printf("seed = %d\n", seed);
srand(seed); //NOTE: i seed random from the command line
unsigned char *p[8];
for(int i = 0; i < 8; i++){
int random_number = rand() % 255;
char random_number_string[8];
itoa(random_number, random_number_string, 10);
p[i] = random_number_string;
//below is just to check
printf("p[%d] = %s\n", i, p[i]);
}
// below i comment out irrelevant parts of the code
//unsigned char byte0[8];
//itoa( (rand() % 256), byte0, 10);
//printf("byte0 = %s\n", byte0);
//printf("Binary values: \n");
for(int n = 0; n < 8; n++){
printf("p[%d] = %s\n", n, p[n]);
//PRINTBIN((int)p[i]);
//printf("\n");
}
return 0;
The result of all this is:
seed = 1054480
p[0] = 81
p[1] = 66
p[2] = 36
p[3] = 32
p[4] = 81
p[5] = 245
p[6] = 33
p[7] = 72
p[0] = 72
p[1] = 72
p[2] = 72
p[3] = 72
p[4] = 72
p[5] = 72
p[6] = 72
p[7] = 72
I'm just wondering what I'm doing to overwite all those values. Thanks.
In your code, p is an "array" of 8 pointers to char. This means that you are storing an address location in the array p.
If you print the addresses along with the data like so -
printf("p[%d] = %s\n", i, p[i]);
printf("%d\n", p[i]);
You will notice that all the values in the array (p) are same, i.e. all the elements in the array are "same" and that is exactly what is your output shows from the second for() loop. This address is the address of the local variable random_number_string.
The first loop is printing different data as the first loop is changing the data in every iteration and after the last iteration, this address location contains the "last" value set.
Hope this clarifies the behavior that you are seeing.
Each iteration of the first cycle creates a new instance of its local char random_number_string[8]; array and then destroys it at the end. On each iteration of that cycle you are storing a pointer to the beginning of that random_number_string array in p[i]. Each pointer p[i] becomes "sour" (dangling) at the end of each i-th iteration. Thus all p[i] values end up invalid. Any attempts to access these values result in undefined behavior.
And this is exactly what your second cycle does. The behavior of your program is undefined.
Note, BTW, that it is incorrect to say that all of your array elements point to the same memory location (as some answers here do). Your array p contains invalid, indeterminate pointer values. Nothing definitive can be said about these values.
Each iteration of your first loop defines 'char random_number_string[8]' and the space for this is allocated from the stack frame. Each iteration does not increase the size of the stack frame, but is going to reuse the same stack space as the prior iteration, meaning that each time around random_number_string will be found at exactly the same address. And since you are placing the address of random_number_string into every element of your 'p' array, every element holds the same value. Whatever you place at that address will be pointed to by every element in your array.
But there's another, issue with your code. You have placed the address of an auto variable into another data structure, The problem is that stack frame that contained random_number_string is popped off the stack at the end of each iteration of your first loop, and will be reused by subsequent stack frames / code blocks.
If you know in advance the maximum size of all of these strings, then you can simply pre-allocate the lot of them with a two dimensional array. Here is the code written with this approach:
int main(int argc, char *argv[]) {
unsigned int seed = atoi(argv[1]);
printf("seed = %d\n", seed);
srand(seed); //NOTE: i seed random from the command line
unsigned char p[8][10];
for(int i = 0; i < 8; i++){
int random_number = rand() % 255;
itoa(random_number, p[i], 10);
printf("p[%d] = %s\n", i, p[i]);
}
for(int n = 0; n < 8; n++){
printf("p[%d] = %s\n", n, p[n]);
}
return 0;
}
Alternatively, you could dynamically allocate them (from the heap). Depending your program, you may need to free them when you are done with them.
int main(int argc, char *argv[]) {
unsigned int seed = atoi(argv[1]);
printf("seed = %d\n", seed);
srand(seed); //NOTE: i seed random from the command line
unsigned char *p[8];
for(int i = 0; i < 8; i++){
int random_number = rand() % 255;
p[i] = (unsigned char *)malloc(10 * sizeof(unsigned char));
itoa(random_number, p[i], 10);
printf("p[%d] = %s\n", i, p[i]);
}
for(int n = 0; n < 8; n++){
printf("p[%d] = %s\n", n, p[n]);
}
return 0;
}

Classical Array Implementation Using Pointers and Memory Allocation

So I got this question from a competition website and I am completely puzzled. Here it is:
Which of the following memory allocation code for p[10][10] confirms perfectly to classical definition of an array? The options are:
char **p;
int i;
p = (char**)malloc(10*sizeof(char*));
*p = (char*)malloc(10*sizeof(char));
for(i = i; i<10; i++)
p[i] = p[0] +10*i;
char **p;
int i;
p = (char**)realloc(p, 10*sizeof(char*));
*p = (char*)realloc(p, 10*sizeof(char));
for(i = i; i<10; i++)
p[i] = p[0] +10*i;
char **p = NULL;
int i;
p = (char**)malloc(10*sizeof(char*));
*p = (char*)malloc(10*sizeof(char));
for(i = i; i<10; i++)
p[i] = (char*)realloc(p[i-1], 10*i*sizeof(char));
char **p;
int i;
p = (char**)malloc(10*sizeof(char*));
for(i = i; i<10; i++)
p[i] = (char*)malloc(10*sizeof(char));
I am completely puzzled. Any ideas are most welcome. Thanks.
EDIT: If none of them are are correct, what would be the correct implementation? A bit of explanation is most welcome as I am preparing for aa competitive exam that requres these skills which ask questions like this (most of which has obvious 'side effects' :( ). Also edited the typos.
None. This one does:
char (*p)[10] = malloc(10*sizeof(*p));
Explanation:
p is declared as a pointer to an array of ten chars. Since it points to an array, sizeof(*p) returns the size of that array, which is 10. So, the malloc() call allocates memory for ten such arrays, i. e. 100 bytes.
Now, when you derefence the pointer as in p[3], the value is the fourth array in the slap of memory. However, this value decays to a pointer to its first element in almost all contexts, so when you say p[3][5] the value is the 6th element within the 4th array within the memory slap.
Sorry, if this sounds a bit confusing, but it's really the same thing that's happening when you declare an array with char array[10][10];, except that the memory comes from a different place.
First things first : do not cast the return value of malloc in C. This is not your code, but anyway, it is always good to say.
Also, the loops should be rewritten like so : for(i = 1; i < 10; i++) or maybe for(i = 0; i < 10; i++). i = i is probably an error (what is that website, again ?), and I will assume so.
char **p;
int i;
p = malloc(10*sizeof(char*));
*p = malloc(10*sizeof(char));
for(i = 1; i < 10; i++)
p[i] = p[0] + 10*i;
This first code allocates 10 char* to p, and then 10 char to *p, which is equivalent to p[0]. Then, it puts the addresses of an unallocated 2D array into the other values of p[i] for i from 1 to 9. Since the array is not allocated (or only partially - p[0] is allocated), this is pretty bad.
char **p;
int i;
p = realloc(p, 10*sizeof(char*));
*p = realloc(p, 10*sizeof(char));
for(i = 1; i < 10; i++)
p[i] = p[0] + 10*i;
This second code uses realloc instead of malloc, which does not solve the previous problems, but also adds probable segmentation faults : realloc on an uninitialized pointer is a bad idea.
char **p = NULL;
int i;
p = malloc(10*sizeof(char*));
*p = malloc(10*sizeof(char));
for(i = 1; i < 10; i++)
p[i] = realloc(p[i-1], 10*i*sizeof(char));
This third code does the same as the first one for the first part, but then uses realloc on p[i] for i starting with 0. I assume realloc deallocates the pointer you pass to it, so this is not really a good idea. And the 10*i*sizeof(char) is not a good idea either. Basically, you will have p[9] allocated with 90 char, and nothing else. And, by the way, initializing p to NULL here doesn't do anything.
char **p;
int i;
p = malloc(10*sizeof(char*));
for(i = 0; i < 10; i++)
p[i] = malloc(10*sizeof(char));
This fourth code has something good at least : it allocates separately each p[i] for i from 0 to 9 (I assume i starts with 0 here, unlike in the other codes). So, this might be the answer you are looking for.
Finally, the question is badly formulated since none of these codes have the same semantics as a declaration like char p[10][10].
Edit :
If you want a dynamically allocated 2D array, you can use this for instance :
int i;
char **p = malloc(10 * sizeof *p);
for(i = 0; i < 10; i++)
p[i] = malloc(10 * sizeof *p[i]);
You can also, as cmaster did, use a pointer to an array type (like char[10]). This is the exemple from cmaster : char (*p)[10].
Well let's see:
This will likely lead to errors because p[1][0] (among others) points to invalid memory locations.
This is undefined behavior because you pass an uninitialized pointer to realloc().
That code possibly leaves uninitialized pointers all over the place.
This code loops from [1, 10), where I would expect [0, 10). So it's also terrible.
Therefore:
All of these are terrible. The correct code is either:
char (*p)[10] = malloc(10 * sizeof(*p));
Or:
char **p = malloc(10 * sizeof(*p));
for (int i=0; i<10; ++i)
p[i] = malloc(10 * sizeof(**p));

Dynamic two dimensional array seems to allocate more memory

I'm trying to allocate a dynamic two dimensional array in C using the following code:
int **allocateMatrix(int rows, int columns) {
int i = 0;
int **p = NULL;
p = (int**) calloc(rows, sizeof(int*));
for(; i < rows; i++) {
p[i] = (int*) calloc(columns, sizeof(int));
}
return p;
}
The code works but actually it's allocating double the memory it needs.
For example, if i pass the arguments rows = 2 and columns = 3 i get an array that's 2 rows by 8 columns.
Am i doing something wrong?
Thank you.
Edit:
The content of the matrix (which is loaded from a file) is:
-1 5 0
4 0 2
And this is what the memory looks like after the allocation and the assignment of the values:
It is allocating the correct amount of memory, but it allocating more memory than a simple 2D array would use because what you've created is not a simple 2D array.
Assuming a 32-bit system (so sizeof(int) == sizeof(int *), and sizeof(int) == 4), then:
a simple 2D array needs 2 x 3 integers = 6 x 4 = 24 bytes
a dynamic 2D array needs 2 pointers plus 2 x 3 integers = 8 x 4 = 32 bytes
That's before there's any accounting for overhead in the memory allocations. So not twice, but more.
The advantages of what you're doing is you can write p[i][j] and get the right result. If you simulated a simple 2D array, you'd have to do the subscript calculation yourself: p[i*3+j] or use (*p)[i][j], depending on exactly how you defined the pointer p.
AFAICT, your screenshot of the array having 20 elements is because.. you told Netbeans (with that #20) to display 20 elements starting at a memory location (**(matrix)). What happens when you change it to be '#3'?
However, based on this comment:
Actually it's more than the double. I know because when i try to assign values they're not contiguous in memory but they are shifted (i can see it from the watches in the debug window in netbeans).
When you allocate memory, you're calling a library that figures out how to request from the operating system what space it may use and then of what space it's been given by the operating system what it hasn't used yet.
You're making assumptions about how the allocator works that may or may not be correct. It's possible for it to allocate space efficiently in a way you don't expect, especially due to virtual paging mechanisms. In short, contiguous calls to the allocator are not guarenteed to allocate contiguous memory, and rarely will.
If you want to use an array-of-pointers for a double array style structure and absolutely must have contiguous addresses in a more "expected" way, you can try this:
int **allocateMatrix(int rows, int columns) {
int i = 0;
int **p = NULL;
int *d = NULL;
p = (int**) calloc(rows, sizeof(int*));
d = (int*) calloc(rows * columns, sizeof(int));
for(; i < rows; i++) {
p[i] = d + i * columns;
}
return p;
}
(code not tested)
that's not because it haves a bidimensional array size (rows*columns*sizeof(int*)) to store the pointers and a bidimensional array space to store the real values (rows*columns*sizeof(int))?
You can use the following approach (no extra memory needed for storing data, actually 1D continuous array in memory):
#include <stdlib.h>
#include <stdio.h>
int (*allocateMatrix(int rows, int columns))[]{
int (*p)[columns] = calloc(rows, columns * sizeof(int)),
i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
p[i][j] = rows*i + j;
}
}
return p;
}
int main(int argc, char *argv[]) {
int rows = 4, cols = 5,
(*array)[cols] = allocateMatrix(rows,cols);
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
printf("array[%d][%d] = %2d\n", i, j, array[i][j]);
}
}
free(array);
return 0;
}
Output:
array[0][0] = 0
array[0][1] = 1
array[0][2] = 2
array[0][3] = 3
array[0][4] = 4
array[1][0] = 4
array[1][1] = 5
array[1][2] = 6
array[1][3] = 7
array[1][4] = 8
array[2][0] = 8
array[2][1] = 9
array[2][2] = 10
array[2][3] = 11
array[2][4] = 12
array[3][0] = 12
array[3][1] = 13
array[3][2] = 14
array[3][3] = 15
array[3][4] = 16

How many bytes are dynamically allocated in the following code segment?

Assuming that a memory address occupies 4 bytes and a char occupies 1 byte:
char** t;
t = malloc(5 * sizeof(char*));
int i;
for (i = 0; i < 5; i++)
t[i] = malloc(sizeof(char) * (i+1));
A minimum of around 35 bytes -- but a typical implementation of malloc will have some minimum allocation size it supports, so in reality, you can expect it to use more memory than that (though exactly how much more will vary).
In a typical case, the minimum allocation will be something like 16 or even 32 bytes, in which case most of the sizes you specified above don't really make any difference -- the last 5 allocations will all be of whatever the minimum happens to be. In a typical case, sizes larger than that will be rounded up to the next power of 2 as well.
That would give 32 bytes for your first allocation, and either 16 or 32 (i.e., the minimum supported size) for each of your other five, for a total of either 112 or 192 bytes.
35 bytes (Look below for breakup)
char** t;
t = malloc(5 * sizeof(char*)); // 5 * 4 = 20 bytes
int i;
for (i = 0; i < 5; i++)
t[i] = malloc(sizeof(char) * (i+1)); //1 + 2 + 3 + 4 + 5 = 15 bytes
Let the computer compute for you:
char** t;
t = (char**) malloc(5 * sizeof(char*));
int i;
for (i = 0; i < 5; i++)
t[i] = (char*) malloc(sizeof(char) * (i+1));
unsigned int sz = 5 * sizeof(char*);
for (i = 0; i < 5; i++)
sz += sizeof(char) * (i+1);
printf("%d\n", sz);
35 on a 32 bits machine.
20 for that
t = malloc(5 * sizeof(char*));
15 for that: 5+4+3+2+1
int i;
for (i = 0; i < 5; i++)
t[i] = malloc(sizeof(char) * (i+1));
Get how many bytes are allocated ON YOUR SYSTEM with, for example
#define malloc(s) mm(s)
void *mm(size_t s) {
printf("allocating %d ...\n", (int)s);
return (malloc)(s);
}
/* your code */
Of course, you can sum the sizes instead of printing them.
The malloc() allocates space rounded up to 16 bytes (at least in win32), so you'll use 32 bytes in the first alloc and 16*5 in the loop.
There is also overhead of malloc (both, time and memory), because malloc() puts a special header, _CrtMemBlockHeader before the memory area it returns (that's why you have to give exactly the same pointer to the free() and are able to use functions like _msize().
So, the memory amount actually used would be 32 + 80 = 112 bytes.
Considering also the overhead for header: + 5 * sizeof(__CrtMemBlockHeader)
the final amount can be as high as 300 bytes, that is ~8 times larger than the expected 35.

Resources