malloc and pointer questions - c

We were shown this program in class yesterday and i have a question regarding it's output.
malloc.c:
#include <stdlib.h>
int *create_array(int);
int *create_array(int elements) {
int i,*x = (int *) malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
free(x);
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
return 0;
}
Question(s):
When i run the program, i get this as output:
1627793032
1627793104
2
3
4
However, shouldn't the first 2 elements be 0 and 1 respectively? The values printed here seem like memory addresses to me, am i right? Also, is this due to some mistake causing undefined behavior?

After free(x);, the values pointed to by x are no longer valid. The memory can be reused for some other purpose, and meanwhile the memory allocation library can use the storage as it sees fit.
So, yes, it is a mistake resulting in undefined behaviour.

The real question is why do you even expect it to work? You free x, then you return a freed pointer which is nonsense.
What is happening is the following:
Inside the function you allocate 5 spaces, x points to the first
one's address.
You write 0, 1, 2, 3, 4 in these spaces.
You free x, so all the 5 spaces are not reserved anymore.
You exit the function, doing so the 2 next free memory spaces are
used, which happen to be the ones where you wrote 0 and 1.
You print the values contained in the 5 memory areas you've already
freed, where the ones in which you wrote 0 and 1 happen to have been
reused for something else; hence the weird numbers.
As a general rule, do not attempt to read areas of memory i've freed; even worse, do not try to WRITE there.
Accessing unallocated memory leads to undefined behaviour.
Also, you don't need to declare the function in a separate row if it's going to have nothing in between; plus you don't have to cast what's returned by malloc to the type; it's a void* that by default can hold anything you throw at it. What matters is your base variable type. See here
Corrected code:
#include <stdlib.h>
int *create_array(int elements) {
int i,*x = malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
free(arr);
return 0;
}

Related

C - Avoiding warning "address of stack memory associated with local variable returned"

I've written the following simple program that sums up the numbers from 0 to 9:
#include <stdio.h>
#include <stdlib.h>
int* allocArray() {
int arr[10];
return arr;
}
int main(void){
int* p;
int summe = 0;
p = allocArray();
for(int i = 0; i != 10; ++i) {
p[i] = i;
}
for(int i = 0; i != 10; ++i) {
summe += p[i];
}
printf("Sum = %d\n", summe);
}
The code compiles and delivers the expected result "45". However I get the following warning: 'address of stack memory associated with local variable
'arr' returned'. What am I doing wrong?
This is undefined behaviour, plain and simple. The only reason it "works" is because with this particular compiler the stack hasn't been trashed yet, but it is living on borrowed time.
The lifetime of arr ends immediately when the function call is complete. After that point any pointers to arr are invalidated and cannot be used.1
Your compiler uses stack memory to store local variables, and the warning indicates that you're returning an address to a now-invalidated stack variable.
The only way to work around this is to allocate memory dynamically and return that:
int* allocArray() {
int* arr = calloc(10, sizeof(int));
return arr;
}
Where you're now responsible for releasing that memory later.
You can also use static to extend the lifetime of arr:
int* allocArray() {
static int arr[10];
return arr;
}
Though this is not without consequences, either, as now arr is shared, not unique to each function call.
1 Like a lot of things in C there's significant overlap between what you "cannot do" because they lead to undefined behaviour and/or crashes and what you "can do" because it's permitted by the syntax and compiler. It's often your responsibility to know the consequences of any code you write, implied or otherwise.
To keep it in your code:
int arr[10];
will allocate the memory on the stack. As soon as you are leaving the function, the content of that array will be overwritten pretty soon. You want to allocate this on the heap.
You would need to use
int* arr = malloc(sizeof(int)*10);
and in the main function, after you've used it (at the end of main), call
delete[] arr;
Nevertheless, this code could be better if the ownership of the array would be properly handled. You want to make yourself familiar with C++ containers and shared/unique pointers.

Is malloc() initializing allocated array to zero?

Here is the code I'm using:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
int i;
for (i = 0; i < sz; ++i) {
if (arr[i] != 0) {
printf("OK\n");
break;
}
}
free(arr);
return 0;
}
The program doesn't print OK. malloc isn't supposed to initialize the allocated memory to zero. Why is this happening?
malloc isn't supposed to initialize the allocated memory to zero. Why is this happening?
This is how it was designed more than 40 years ago.
But, at the same time, the calloc() function was created that initializes the allocated memory to zero and it's the recommended way to allocate memory for arrays.
The line:
arr = (int *)malloc(sz * sizeof(int));
Should read:
arr = calloc(sz, sizeof(int));
If you are learning C from an old book it teaches you to always cast the value returned by malloc() or calloc() (a void *) to the type of the variable you assign the value to (int * in your case). This is obsolete, if the value returned by malloc() or calloc() is directly assigned to a variable, the modern versions of C do not need that cast any more.
The man page of malloc says:
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that can
later be successfully passed to free().
So malloc() returns uninitialized memory, the contents of which is indeterminate.
if (arr[i] != 0)
In your program, You have tried to access the content of a memory block, which is invoked undefined behavior.
malloc isn't supposed to initialize the allocated memory to zero.
Memory allocated by malloc is uninitialised. Value at these locations are indeterminate. In this case accessing that memory can result in an undefined behavior if the value at that location is to be trap representation for the type.
n1570-§6.2.6.1 (p5):
Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. [...]
and footnote says:
Thus, an automatic variable can be initialized to a trap representation without causing undefined behavior, but the value of the variable cannot be used until a proper value is stored in it.
Nothing good can be expected if the behavior is undefined. You may or may not get expected result.
From the C Standard 7.22.3.4:
Synopsis
#include <stdlib.h>
void *malloc(size_t size);
Description
The malloc function allocates space for an object whose size is
specified by size and whose value is indeterminate.
The value is indeterminate. So, every compiler is free to behave how it wants. For example, in Microsoft Visual C++, in Debug mode, the area of allocated memory by malloc() is all set to 0xCDCDCDCD and when in Release mode it is random. In modern versions of GCC, it is set to 0x000000 if you don't enable code optimizations, and random otherwise. I don't know about other compilers, but you get the idea.
void *malloc(size_t size) is just supposed to keep aside the specified amount of space. That's all. There is no guarantee as to what will be present in that space.
Quoted from the man pages:
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that can
later be successfully passed to free().
Apart from calloc() you can use the memset() function to zero out a block of memory.
The first time you call malloc(3), it asks to the operating system to get memory for the heap space.
For security reasons, the unix/linux kernel (and many other operating systems) in general zeroes the page contents that is to be given to a process, so no process can access that memory's previous contents and do nasty things with it (like searching for old passwords, or similar things).
If you do several allocations and deallocations of memory, when the malloc module reuses the previous memory, you'll see garbage coming from malloc(3).
Zero's are assigned to page contents at first time in linux kernel.
Below program explains the memory initialisation difference in malloc and calloc:
#include<stdio.h>
#include<stdlib.h>
#define SIZE 5
int main(void) {
int *mal = (int*)malloc(SIZE*sizeof(int));
int *cal = (int*)calloc(SIZE, sizeof(int));
mal[4] = cal[4] = 100;
free(mal); free(cal);
mal = (int*)malloc(SIZE*sizeof(int));
cal = (int*)calloc(SIZE, sizeof(int));
for(int i=0; i<SIZE; i++) {
printf("mall[%d] = %d\n", i, mal[i]);
}
for(int i=0; i<SIZE; i++) {
printf("call[%d] = %d\n", i, cal[i]);
}
}
I use malloc to allocate everything from the heap(dynamic memory) while i should use calloc instead nowaday , and memset is great for filling you memory segment with any chosen character.
Compile and work great with GCC:
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
int main()
{
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
memset(arr, 0, sz*sizeof(int) );
int i;
for (i = 0; i < sz; ++i) {
if (arr[i] != 0) {
printf("OK\n");
break;
}
}
free(arr);
return 0;
}
ref: http://www.cplusplus.com/reference/cstring/memset/
well, the value is not initialized in malloc.
And it does print "OK" in VS Code.
so in VS Code, the output is : "OK" followed by a garbage value.
in a web based compiler (here's the link : https://www.programiz.com/c-programming/online-compiler/ ),
the output was
"LOL" followed by '0'
so some compilers do initialize the value..but actually the value in malloc is not intialized. so it will return a garbage value when printed as in the above example in VS Code.
int main()
{
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
int i;
for (i = 0; i < sz; i++)
{
if (arr[i] != 0)
{
printf("OK\n");
break;
}
else
{
printf("LOL \n");
break;
}
}
printf("%d", arr[0]);
free(arr);

C: Free temporary array produced by malloc-function

I have a c function that produces my a int array using malloc. It works quiet well and I think it isn't really important what it does because the problem doesn't really have anything to do with that. (In this case it calculates the numbers to a given int and base). I need this array temporary in a function, which might be a sub function of a sub function of a ... (you got the idea, point this function can be used several times) and before the return I would like to run free, but it doesn't work. Here is a testing code (it sorts an array of ints to the amount of ones in their binary representation using qsort (yes I know could have calculated the results more directly, but the point is the probleme I run into when trying to run free (here comment out in function ones))):
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25, 0, 15};
int * baseString(int u, int base);
int abs(int a);
int ones(int a);
int cmpfunc (const void * a, const void * b)
{
return ones(*(int*)a)>ones(*(int*)b);
}
int main()
{
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 7; n++ )
{
printf("%d ", values[n]);
}
qsort(values, 7, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 7; n++ )
{
printf("%d (Ones=%d) ", values[n], ones(values[n]));
}
printf("\n");
return(0);
}
int abs(int a){
return (a<0)? a*-1:a;
}
int* baseString(int u, int base){
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1;
if(base<2){
r[2]=-1;
return r;
}
int negativ=0;
if(u<0){
u=abs(u);
negativ=1;
}
int i=2;
do{
int ur=u%base;
r[i]=ur;
u/=base;
i++;
}while(u>0);
r[1]=i-1;
if(negativ){
r[1]=-r[1];
}
return r;
}
int ones(int a){
int* ai=baseString(a, 2);
int a1=1;
for(int i=2; i<abs(ai[1]); i++){
if(ai[i]==1){
a1++;
}
}
if(!a){
a1=0;
}
//free(ai);
return a1;
}
PS: I am quiet sure this thread is duplicate of some tread somewhere, but I didn't found it.
Part of your problem is actually quite simple.
In your baseString() function, the first three lines are
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1;
The malloc() dynamically allocates a single int, or an array with one element. The r[1] = 1 modifies the second element of that array which has one element.
The result of that is undefined behaviour. A common symptom of running off the end of an array like this is corrupting memory in your program, such as that used internally by malloc() and free() to keep track of allocated and released memory. Which would explain your problem.
Make sure you allocate the number of elements needed. For example, if 10 elements are needed, malloc(10*sizeof(int)). You need to work out the number needed, since dynamically arrays will not magically grow to get the number of elements needed.
I haven't look further, so there may be other problems. But this one is pretty glaring.
It is also a good idea to check that malloc() actually succeeds. It returns NULL if it fails.
The key problem here appears to an ABW (Array Bounds Write). In the baseString function, you are actually allocating memory which is equivalent to the size of 1 integer, but are trying to access it like an array in r[1],r[2], r[i] etc, which results in write to memory which technically doesn't belong to you.
The code snippet in your code corresponds to
int* r=malloc(sizeof(int));
r[0]=base;
r[1]=1; //ABW here
if(base<2){
r[2]=-1; //ABW here
return r;
}
do{
int ur=u%base;
r[i]=ur; //ABW here
u/=base;
i++;
}while(u>0);
This might lead to undefined behavior at any point of time in your code. In your case, it seems to be affecting free as the memory overwrite may have messed up with the internal book keeping data of malloc and free implementation.

malloc-> how much memory is allocated? [duplicate]

This question already has answers here:
I can use more memory than how much I've allocated with malloc(), why?
(17 answers)
Closed 9 years ago.
As I know that malloc allocate a specific number of bytes in the memory. However I am trying to use it and I allocate 4 bytes but it gives me NO error when I try to store more than 4 (up to 200 integers) elements in the array!! So in my code I don't need to use realloc!! I'm using Linux by the way. Finally I will pleased to hear any advice from you ... thanks in advance.
tmp.h :
#ifndef TMP_H
#define TMP_H
#define MAXLENGTH 4
#define GROWFACTOR 1.5
typedef struct stVector
{
int *vec;
int length;
int maxLength;
}Vector;
Vector newEmptyVector();
void addElement(Vector *vec, int elt);
#endif
tmp.c :
#include "stdio.h"
#include "stdlib.h"
#include "tmp.h"
Vector newEmptyVector()
{
Vector vec;
vec.vec = (int*) malloc(0);
printf("Allocating %d bytes\n", sizeof(int)*MAXLENGTH );
vec.length = 0;
vec.maxLength = MAXLENGTH;
return vec;
}
void addElement(Vector *vec, int elt)
{
/*if(vec->length == vec->maxLength)
{
vec->vec = (int*)realloc(vec->vec,sizeof(int)* vec->maxLength * GROWFACTOR);
vec->maxLength = vec->maxLength * GROWFACTOR;
}*/
vec->vec[vec->length++] = elt;
}
main.c :
#include"tmp.h"
int main(int argc, char const *argv[])
{
Vector vector = newEmptyVector();
printf("The length is %i and maxlength is ` `%i\n",vector.length,vector.maxLength);
addElement(&vector,5);
addElement(&vector,3);
addElement(&vector,1);
addElement(&vector,7);
printf("The length is %i and maxlength is ` `%i\n",vector.length,vector.maxLength);
addElement(&vector,51);
printf("The length is %i and maxlength is %i\n",vector.length,vector.maxLength);
for (int i = 0; i < 200; ++i)
{
addElement(&vector,i);
printf("The length is %i and maxlength is %i\n" ,vector.length, vector.maxLength);
}
return 0;
}
Using memory you haven't allocated invokes undefined behavior. Don't do that. In all likelyhood, Linux has give your program a page of memory, and you haven't overrun that yet. If you touch memory not allocated to your program the OS should cause your program to segfault. But it's possible that any other mallocing you do will also use parts of that page, and you'll end up corrupting your data.
Not having runtime checks for overrunning buffers is part of what makes C fast, but it puts more on the programmer not to do dumb things.
The fact that (simply because there is no bound checking in C) no error is raised does not mean that you can safely use memory outside requested bounds. You were lucky not to cause a segmentation fault, you have just fallen into a memory region that is not claimed by your malloc (let's say, it's not yours).
You can write there, but there is no guarantee that you won't be overwriting memory assigned to another malloc or, conversely, that the "extra" part will not be allocated to some other malloc. In your case, the memory region you are writing into appears not to be claimed (yet).
Regarding your specific issue:, I allocate 4 bytes but it gives me NO error when I try to store more than 4.
Keep in mind, something like:
int *anyVar = (int)malloc(0);
anyVar[0] = 12; //Will eventually invoke undefined behavior.
writing to memory you do not own will eventually invoke undefined behavior. The bad thing is that your results can seem good, and even repeatable for many runs of the code. But at some point, your code will fail.
This is how you should allocate: (by the way)
int numIntsInArray = 100;
int *anyVar = malloc(sizeof(int)*numIntsInArray);//note:do not cast output of malloc
anyVar[0] = 1;//first element of anyVar
anyVar[99] = 1000;//last element of anyVar
Do not forget to free all memory:
free(anyVar);
Other examples of undefined behavior in C & C++:
The examples of bad code below can be done, and you will likely get no compiler warnings, and may even get
expected results during run-time, but with this code, nothing is guaranteed. (exception: good examples)
char * p = "string"; // Badly formed C++11, deprecated C++98/C++03
p[0] = 'X'; // undefined behavior
Create an array instead:
char p[] = "string"; // Good
p[0] = 'X';
C++, you can create/use a standard string like this:
std::string s = "string"; // Good
s[0] = 'X';
Division by zero results in undefined behavior:
int x = 1;
return x / 0; // undefined behavior
Some pointer operations may lead to undefined behavior:
int arr[4] = {0, 1, 2, 3};
int* p = arr + 5; // undefined behavior
Leaving a non-void function without returning a value
int func(void)
{
//undefined behavior
}
Unspecified or implementation-defined behavior:
printf("%d %d\n", ++n, power(2, n)); //Bad
i = ++i + 1; //Bad
i = i + 1; // Okay

Return an array with all integers from a to b

The exercise says "Create a function with two parameters a and b which are integers and the function will return an array of integers with every number from a to b.
#include <stdio.h>
#include <stdlib.h>
void exc(int a, int b){
int i,k=0,d[k];
for(i=a;i<=b;i++){
d[k]=i;
k++;
printf("%d ",d[k]);
}
}
int main(void){
int c,d;
printf("Give first integer: ");
scanf("%d",&c);
printf("Give second integer: ");
scanf("%d",&d);
exc(c,d);
system("pause");
}
The problem is that if I put for example c=2 and d=5 the program returns something like 2088806975 16384 1 2293536 instead of 2 3 4 5. Where is the problem? Thanks
For starters
If your main() has return type int, don't forget to return a value from it!
int main(void)
{
/* code here */
return 0;
}
Problem 1
By
d[k]=i;
k++;
printf("%d ", d[k]);
I think you meant
d[k]=i;
printf("%d ", d[k]);
k++;
otherwise you're printing the "next" array element each time, which will be one-past-the-end of the array on the last loop iteration.
Problem 2
int i,k=0,d[k];
You make an array d of size k where k is 0. I think you intended for the array to automatically resize when you write k++, but this is not the case. The array is created with zero elements, and then that's its size for all time.
Your next instinct may be to create the array big enough in the first place:
int d[b-a+1];
Unfortunately, this is most likely wrong, too. It relies on a feature called Variable Length Arrays (or "VLAs"); although a GCC compiler extension (and, incidentally, C99) does allow this (and it's not clear whether you have that extension enabled and/or are allowed to use it in your homework — I will assume for this answer that you do not / are not), the language itself does not allow an array with a dynamic size.
What do I mean by dynamic size?
I mean that the variables a and b depend on user input: they are not known at compile-time. In general, the size of an array must be known at compile-time.
Note: If you use this, your code may compile without error, and your program may even appear to run and work correctly. However, you'd be relying on what's called "Undefined Behaviour", and your code could stop running or even crash at any time, due to any number of random, unpredictable factors. Even if it looks like it's okay, it's invalid. Don't do it!
Solution
Fortunately, there is a way to allocate a block of memory with the right size for your elements, when you don't know the elements until your program runs. It's called "dynamic allocation", and it involves a function call:
int *d = malloc(sizeof(int) * (b-a+1));
You can use the same syntax (d[k]) to access "elements" in this "array" or block of memory, but you must later manually free the memory:
free(d);
Possible problem 3
Your assignment says to return an array from the function, but you're not doing this. Instead, you're just creating, filling and printing the array all within the same function (which seems a bit pointless).
You can't actually return an array either, but since you're dynamically allocating the space for it, you have a pointer to work with. It's my opinion that your teacher may have wanted you to return a pointer to this array.
If so, the finished code looks a bit like this:
#include <stdio.h>
#include <stdlib.h>
int *exc(int a, int b)
{
int i, k = 0;
int *d = malloc(sizeof(int) * ((b-a)+1));
for (i=a; i<=b; i++) {
d[k]=i;
k++;
}
return d;
}
int main(void)
{
int a,b,i,*ar;
printf("Give first integer: ");
scanf("%d",&a);
printf("Give second integer: ");
scanf("%d",&b);
ar = exc(a,b);
for (i=0; i < (b-a+1); i++) {
printf("%d ", ar[i]);
}
free(ar);
system("pause");
return 0;
}
Disclaimer: I'm rusty on C, so the finished code might have a few syntax bugs.
Hope this helps!
The size of d is always 0. Since you are initializing it as d[k]. You should instead do something like d[b-a+1].
Update:
Furthermore, the order of your statements are wrong, see pmg's answer.
Update 2:
Your code doesn't actually return the array you are creating and it won't work unless you create the array on the heap (ie. using malloc / free).
The order of statements is not correct
d[k]=i; // d[0] = 42;
k++; // ...
printf("%d ",d[k]); // print d[1]
You need to allocate the memory for the array first, use malloc with the amount of integers you need to assign
Also, to be true to the problem statement, have the function return a pointer to the array so the main function can print it out instead of the exec function doing it directly.
Doing somebodys homework is always somewhat bad but obviously OP has no idea how to aproach this particular problem so here is a full example of dynamic memory allocation (overly commented).
#include <stdio.h>
#include <stdlib.h> /* required for malloc() and free() */
/* function that retuns a pointer to int type of data */
int *create_array(int a, int b)
{
int *array;
int array_size = b - a + 1; /* assuming that 'a' is always smaller than 'b' */
int i;
array = malloc( array_size * sizeof(int) ); /* allocate memory for the array */
if(array == NULL) exit(EXIT_FAILURE); /* bail out if allocation fails */
/* assign the values into array */
for(i = 0; i < array_size; ++i)
array[i] = a++;
/* return a pointer to our allocated array */
return array;
}
int main(void)
{
int *array;
int i, a = 42, b = 50;
/* and now we can call the function to create the array */
array = create_array(a, b);
/* print results */
for(i = 0; i < b - a + 1; ++i)
printf("%d\n", array[i]);
/* always remember to free the data after you are done with it */
free(array);
return 0;
}
You incorrectly declare d array in your code:
int d[k];
should be:
int d[b-a+1];
Edit::
Also, as others have posted, the statement order is wrong:
d[k]=i;
k++;
printf("%d ",d[k]);
should be:
d[k]=i;
printf("%d ",d[k]);
k++;
because otherwise you "lose" the first value when k==0.
You made an array of size zero and then started throwing data in without resizing the array. I'm a bit surprised that you aren't getting an error.
You're accessing data from memory outside the safety of defined data storage. It should be an error because the results are not defined. The data past the end of your array could be used for anything. And since your array is size zero, everything is past the end.
There are a couple problems. First, d is not returned from exc. Of course, you shouldn't just return it since it's allocated on the stack. Secondly, the printf is called after you increment k. That prints the next element in d, not the one whose value you just filled in. Finally, d doesn't have any space allocated for it, since k is always 0 when d is created.
It happens because you allocate memory for d on the stack. If you move the declaration of it outside the function, everything shoud be ok.

Resources