Rust
Understanding C program Compilation Process
graph TD;
A[Components <br>of<br>Compiler]
subgraph Components
B[Preprocessor]
C[Compiler]
B-->C
D[Assembler]
E[Linker]
end
C-->F[Assembly Code]
F-->D
G[Object Code<br> Machine Code]
D-->G
G-->E
H[Libraries]
H-->E
graph LR;
A[//*Hello*/ <br> including studio.h <br>void main/]
B[Preprocessor]
C[/studio.h code file<br>void main/]
A-->B-->C
- Preprocessor will remove comments and include the codes of heder file in the source code
graph LR;
C[/studio.h code file<br>void main/]
D[Compiler]
E[Assembly Code]
C-->D-->E
int main() {
int x = 1;
x = x + 2;
return x;
}
main:
PUSH %BP
MOV %SP, %BP
@main_body:
SUB %SP, $8, %SP
MOV $1, -8(%BP)
MOV $2, -4(%BP)
MOV $5, -8(%BP)
MOV -8(%BP), %13
JMP @main_exit
@main_exit:
MOV %BP, %SP
POP %BP
RET
C to Assembly Convertor
graph LR;
E[Assembly Code]
F[Assembler]
G[Object File]
E-->F-->G
graph LR;
G1[Object File 1<br>1 0 1 1 1 <br>1 0 1 1 1<br>1 0 1 1 1<br>1 0 1 1 1]
G2[Object File 2<br>1 0 1 1 1 <br>1 0 1 1 1<br>1 0 1 1 1<br>1 0 1 1 1]
G3[Object File 3<br>1 0 1 1 1 <br>1 0 1 1 1<br>1 0 1 1 1<br>1 0 1 1 1]
G4[Object File 4<br>1 0 1 1 1 <br>1 0 1 1 1<br>1 0 1 1 1<br>1 0 1 1 1]
G5[Libraries]
H[Linker]
G1-->H
G2-->H
G3-->H
G4-->H
G5-->H
H-->I[exe file]
Let's dive deeper
Structures in C
#include <stdio.h>
struct student
{
int roll;
char name[20];
float marks;
};
int main()
{
struct student s1;
printf("Enter roll: ");
scanf("%d", &s1.roll);
printf("Enter name: ");
scanf("%s", s1.name);
printf("Enter marks: ");
scanf("%f", &s1.marks);
printf("Roll: %d\n", s1.roll);
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
struct student students[5];
for (int i = 0; i < 5; ++i)
{
printf("Enter roll for student %d: ", i + 1);
scanf("%d", &students[i].roll);
printf("Enter name for student %d: ", i + 1);
scanf("%s", students[i].name);
printf("Enter marks for student %d: ", i + 1);
scanf("%f", &students[i].marks);
}
for (int i = 0; i < 5; ++i)
{
printf("\nStudent %d:\n", i + 1);
printf("Roll: %d\n", students[i].roll);
printf("Name: %s\n", students[i].name);
printf("Marks: %.2f\n", students[i].marks);
}
struct student *ptr;
ptr = &s1;
printf("\nUsing pointer:\n");
printf("Roll: %d\n", ptr->roll);
printf("Name: %s\n", ptr->name);
printf("Marks: %.2f\n", ptr->marks);
return 0;
}
Union in C
#include <stdio.h>
#include <string.h>
union student
{
int roll;
char name[20];
float marks;
};
int main(){
union student s1;
printf("Enter roll: ");
scanf("%d", &s1.roll);
printf("Enter name: ");
scanf("%s", s1.name);
printf("Enter marks: ");
scanf("%f", &s1.marks);
printf("Roll: %d\n", s1.roll);
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
union student students[5];
for (int i = 0; i < 5; ++i)
{
printf("Enter roll for student %d: ", i + 1);
scanf("%d", &students[i].roll);
printf("Enter name for student %d: ", i + 1);
scanf("%s", students[i].name);
printf("Enter marks for student %d: ", i + 1);
scanf("%f", &students[i].marks);
}
for (int i = 0; i < 5; ++i)
{
printf("\nStudent %d:\n", i + 1);
printf("Roll: %d\n", students[i].roll);
printf("Name: %s\n", students[i].name);
printf("Marks: %.2f\n", students[i].marks);
}
union student *ptr;
ptr = &s1;
printf("\nUsing pointer:\n");
printf("Roll: %d\n", ptr->roll);
printf("Name: %s\n", ptr->name);
printf("Marks: %.2f\n", ptr->marks);
return 0;
}
Structures vs Union
#include <stdio.h>
#include <string.h>
union student
{
int roll;
char name[20];
float marks;
};
int main(){
union student s1;
s1.roll = 1;
strcpy(s1.name, "John");
s1.marks = 99.99;
printf("Roll: %d\n", s1.roll);
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
s1.roll = 2;
printf("Roll: %d\n", s1.roll);
strcpy(s1.name, "Jane");
printf("Name: %s\n", s1.name);
s1.marks = 100.00;
printf("Marks: %.2f\n", s1.marks);
return 0;
}
Enumeration
#include <stdio.h>
#include <string.h>
enum weeks
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};
int main()
{
enum weeks today;
today = Wednesday;
printf("Day %d\n", today + 1);
for(int i = Monday; i <= Sunday; ++i)
{
printf("Day %d\n", i + 1);
}
return 0;
}
Memory Allocation
#include <stdio.h>
#include <string.h>
int main(){
int a[5];
int a[5] = {1, 2, 3, 4, 5};
int *ptr;
ptr = (int *)malloc(5 * sizeof(int));
free(ptr);
return 0;
}
Malloc
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int n = 5;
int *ptr;
int arr[n];
ptr =(int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
{
*(ptr + i) = i + 1;
}
for (int i = 0; i < n; i++)
{
printf("The value of %d element is: %d\n", i + 1, ptr[i]);
}
free(ptr);
return 0;
}
Calloc
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
int n = 5;
int *ptr;
int arr[n];
ptr =(int *)calloc(n, sizeof(int));
for (int i = 0; i < n; i++)
{
*(ptr + i) = i + 1;
}
for (int i = 0; i < n; i++)
{
printf("The value of %d element is: %d\n", i + 1, ptr[i]);
}
free(ptr);
return 0;
}
Realloc
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
int n = 5;
int *ptr;
int arr[n];
ptr =(int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
{
*(ptr + i) = i + 1;
}
for (int i = 0; i < n; i++)
{
printf("The value of %d element is: %d\n", i + 1, ptr[i]);
}
ptr = realloc(ptr, 10 * sizeof(int));
for (int i = 5; i < 10; i++)
{
*(ptr + i) = i + 1;
}
for (int i = 0; i < 10; i++)
{
printf("The value of %d element is: %d\n", i + 1, ptr[i]);
}
free(ptr);
return 0;
}
Memory Layout of C program
graph LR;
subgraph layout
A[Stack<br>Used for Static Memory Allocation<br>also functions are stored init<br>all recursive functions are added init]
A1[Blank <br> for Stack/Heap]
B0[Blank <br> for Stack/Heap]
B[Heap<br>Used for Dynamic Memory Allocation]
subgraph Data
C1[Uninitialised Data<br>bss]
C2[Initialised Data]
end
D[Text<br> Contains Machine Code]
end
Heap Overflow & Stack Overflow
- When memory limit exceeded due to large allocation of memory in heap, it is called heap overflow.
- We continuously allocate memory in heap and deallocate memory from heap. If we allocate memory in heap
more than the limit of heap, it is called heap overflow.
- We continuously push data into stack and pop data from stack. If we push data into stack more than the
limit of stack, it is called stack overflow.
- When memory limit exceeded due to large allocation of memory in stack, it is called stack overflow.
- Higher dimensional arrays cause stack overflow.
- Recursive functions cause stack overflow.
Buffer Overflow
- Buffer overflow is a vulnerability in low level codes of C and C++.
- Buffer is a temporary storage area in RAM.
- Buffer : Sequential section of memory allocated to contain anything from a character string to
an array of integers.
- Buffers are designed to store data in a sequential manner.
- When a program tries to store more data in a buffer than it was intended to hold, it is called buffer
overflow.
- Buffer overflow can cause program to crash.
- Buffer overflow can cause malicious code to be executed.
- Buffer overflow can cause security vulnerability.
- Buffer overflow can cause data corruption.
- Buffer overflow can cause the program to misbehave.
- In c/c++ due to to dangling pointer, buffer overflow can occur.
- In Rust, buffer overflow cannot occur due to dangling pointer.
- Uust guraantees memory safety.
- Rust is a memory safe language.
- Rust is a system programming language.
- Rust is a multi paradigm language.
- Rust is a compiled language.
- Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees
thread safety.
Why Rust preferrable for developers
- fast
- memory safe
- low overhead
- adaptable
- simple to apply
- strong typed and statically typed
Memory management in Rust
- Rust uses a memory management system that involves ownership, borrowing, and lifetimes.
- Ownership is a unique feature of Rust.
- Ownership is a unique feature of Rust that allows Rust to achieve memory safety without garbage
collector.
- Ownership is a unique feature of Rust that allows Rust to achieve memory safety without reference
counting.