'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?
Solution 1:[1]
mallocisn'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.
Solution 2:[2]
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.
Solution 3:[3]
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.
Solution 4:[4]
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. Ifsizeis 0, thenmalloc()returns either NULL, or a unique pointer value that can later be successfully passed tofree().
Apart from calloc() you can use the memset() function to zero out a block of memory.
Solution 5:[5]
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).
Solution 6:[6]
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]);
}
}
Solution 7:[7]
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;
}
Solution 8:[8]
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);
Solution 9:[9]
I built a proof of concept using a package that I developed called PyLabel to upload annotations to Azure Custom Vision. You can see it here https://github.com/pylabel-project/samples/blob/main/pylabel2azure_custom_vision.ipynb.
PyLabel can read annotations from COCO, YOLO, or VOC format into a dataframe. Once they are in the data frame you can loop through the dataframe of annotations and use the Custom Vision APIs to upload the images and annotations.
The annotation format used by Custom Vision similar to the YOLO format because they both used normalized coordinated between 0-1.
Here is a snippet of the code from the notebook mentioned above:
#Iterate the rows for each image in the dataframe
for img_filename, img_df in dataset.df.groupby('img_filename'):
img_path = str(PurePath(dataset.path_to_annotations, str(img_df.iloc[0].img_folder), img_filename))
assert exists(img_path), f"File does not exist: {img_path}"
#Create a region object for each bounding box in the dataset
regions = []
for index, row in img_df.iterrows():
#Normalize the boundings box coordinates between 0 and 1
x = Decimal(row.ann_bbox_xmin / row.img_width).min(1)
y = Decimal(row.ann_bbox_ymin / row.img_height).min(1)
w = Decimal(row.ann_bbox_width / row.img_width).min(1-x)
h = Decimal(row.ann_bbox_height / row.img_height).min(1-y)
regions.append(Region(
tag_id=tags[row.cat_name].id,
left=x,
top=y,
width=w,
height=h
)
)
#Create an object with the image and all of the annotations for that image
with open(img_path, mode="rb") as image_contents:
image_and_annotations = [ImageFileCreateEntry(name=img_filename, contents=image_contents.read(), regions=regions)]
#Upload the image and all annnotations for that image
upload_result = trainer.create_images_from_files(
project.id,
ImageFileCreateBatch(images=image_and_annotations)
)
#If upload is not successful, print details about that image for debugging
if not upload_result.is_batch_successful:
print("Image upload failed.")
for image in upload_result.images:
print(img_path)
print("Image status: ", image.status)
print(regions)
#This will take a few minutes
print("Upload complete")
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ricky Dev |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | |
| Solution 5 | Luis Colorado |
| Solution 6 | kalaiamuthan manisekar |
| Solution 7 | |
| Solution 8 | Anirban Mitra |
| Solution 9 |
