#+TITLE: Learn Memory Management in C #+AUTHOR: Riyyi #+LANGUAGE: en #+OPTIONS: toc:nil Completed course from [[https://www.boot.dev/courses/learn-memory-management-c][boot.dev]]. The exercises from the course have been worked out in this repository. This is my way of obtaining the "certificate" for free. The first the 3 chapters of the course can be done interactively on the website. [[./bootdev-c.png]] If you're reading this with the intention of completing the exercises yourself, you can find each exercise is in its own directory inside of the =src= directory. Remove all the files that each exercise mentions you should modify, as you go through them. Then recreate the files from the exercise, so you won't get spoiled. Notes: - In order to verify allocations in the unit tests, please use the wrapper functions =boot_malloc=, =boot_calloc=, =boot_realloc= and =boot_free= from =boot_lib.h= instead of the =stdlib.h= allocation functions - In chapter 6 exercise 6, macOS malloc will almost never return a NULL pointer due to virtual memory overcommit, so you should check for ~size == 1024 * 1024 * 100)~ instead of ~array == NULL~ - In chapter 8 and 11, I renamed ~stack_t~ to ~my_stack_t~ due to a =std= naming conflict on macOS ** Build instructions Compiling and running all the tests can be done with the following commands: #+BEGIN_SRC sh $ mkdir build $ cd build $ cmake .. $ make run #+END_SRC ** Output Successful output of all the tests: #+BEGIN_SRC sh $ make run 12:25PM [ 2%] Built target munit [ 5%] Built target 11-10-sweep [ 6%] Built target 04-1-enums [ 7%] Built target 04-2-non-default-values [ 9%] Built target 04-3-switch-case [ 10%] Built target 04-4-sizeof-enum [ 12%] Built target 05-1-union [ 13%] Built target 05-2-memory-layout [ 15%] Built target 05-3-5-4-union-size [ 16%] Built target 05-5-helper-fields [ 17%] Built target 06-1-the-stack [ 19%] Built target 06-2-why-a-stack [ 20%] Built target 06-3-stack-overflow [ 21%] Built target 06-4-pointers-to-the-stack [ 23%] Built target 06-5-the-heap [ 25%] Built target 06-6-malloc [ 27%] Built target 06-7-free [ 28%] Built target 06-8-big-endian-little-endian [ 30%] Built target 07-1-pointer-pointers [ 32%] Built target 07-2-array-of-pointers [ 33%] Built target 07-3-void-pointers [ 35%] Built target 07-4-swapping-integers [ 37%] Built target 07-5-swapping-strings [ 39%] Built target 07-6-generic-swap [ 41%] Built target 08-1-low-level-stack [ 42%] Built target 08-2-stack-push [ 44%] Built target 08-3-stack-pop [ 46%] Built target 08-4-stack-free [ 48%] Built target 08-5-dangerous-push [ 50%] Built target 08-6-multiple-types [ 52%] Built target 09-1-snek-objects [ 53%] Built target 09-2-integer [ 55%] Built target 09-3-float [ 57%] Built target 09-4-string [ 59%] Built target 09-5-vector3 [ 61%] Built target 09-6-arrays [ 62%] Built target 09-7-get-and-set [ 64%] Built target 09-8-length [ 65%] Built target 10-1-garbage-collector [ 67%] Built target 10-2-refcounting [ 69%] Built target 10-3-increment [ 71%] Built target 10-4-decrement-and-free [ 73%] Built target 10-5-vectors [ 74%] Built target 10-6-arrays [ 76%] Built target 10-7-refcounting-review [ 77%] Built target 11-01-handling-cycles [ 80%] Built target 11-02-pros-and-cons [ 82%] Built target 11-03-stack-frames [ 85%] Built target 11-04-tracking-objects [ 88%] Built target 11-05-free [ 91%] Built target 11-06-frame-references [ 94%] Built target 11-07-mark-and-sweep [ 97%] Built target 11-08-mark [100%] Built target 11-09-trace Running test suite with seed 0x3d418efb... colors/are_defined [ OK ] [ 0.00000100 / 0.00000100 CPU ] colors/are_defined_correctly [ OK ] [ 0.00000100 / 0.00000200 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x1447c343... colors/defined [ OK ] [ 0.00000000 / 0.00000100 CPU ] colors/defined_vscode [ OK ] [ 0.00000100 / 0.00000200 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xba550ddb... http/switch_enum [ OK ] [ 0.00000100 / 0.00000100 CPU ] http/switch_enum_default [ OK ] [ 0.00000100 / 0.00000200 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. The size of BigNumbers is 8 bytes The size of HttpErrorCode is 4 bytes Running test suite with seed 0xba8a2b8d... format/integer [ OK ] [ 0.00000200 / 0.00000300 CPU ] format/string [ OK ] [ 0.00000100 / 0.00000100 CPU ] format/integer_nvim [ OK ] [ 0.00000200 / 0.00000200 CPU ] format/string_nvim [ OK ] [ 0.00000100 / 0.00000200 CPU ] 4 of 4 (100%) tests successful, 0 (0%) test skipped. value (set): -420 err (unset): 4294966876 value (unset): -1 err (set): 4294967295 Running test suite with seed 0xa0f30fc8... PacketHeader/test_packet_header_size [ OK ] [ 0.00000100 / 0.00000100 CPU ] PacketHeader/test_tcp_header_fields [ OK ] [ 0.00000100 / 0.00000100 CPU ] PacketHeader/test_field_raw_size [ OK ] [ 0.00000100 / 0.00000000 CPU ] PacketHeader/test_field_to_raw_consistency[ OK ] [ 0.00000100 / 0.00000000 CPU ] 4 of 4 (100%) tests successful, 0 (0%) test skipped. --------------------------------- Stack pointer offset: 0 bytes --------------------------------- Dark mode? --------------------------------- Stack pointer offset: 0 bytes --------------------------------- More like... --------------------------------- Stack pointer offset: 0 bytes --------------------------------- dark roast. Running test suite with seed 0xbd38a5fa... /example/compare [ OK ] [ 0.00000600 / 0.00000500 CPU ] /example/rand [ OK ] [ 0.00000300 / 0.00000300 CPU ] /example/parameters foo=one, bar=red [ OK ] [ 0.00000300 / 0.00000300 CPU ] foo=one, bar=green [ OK ] [ 0.00000300 / 0.00000300 CPU ] foo=one, bar=blue [ OK ] [ 0.00000200 / 0.00000300 CPU ] foo=two, bar=red [ OK ] [ 0.00000300 / 0.00000200 CPU ] foo=two, bar=green [ OK ] [ 0.00000200 / 0.00000200 CPU ] foo=two, bar=blue [ OK ] [ 0.00000200 / 0.00000200 CPU ] foo=three, bar=red [ OK ] [ 0.00000100 / 0.00000200 CPU ] foo=three, bar=green [ OK ] [ 0.00000300 / 0.00000200 CPU ] foo=three, bar=blue [ OK ] [ 0.00000200 / 0.00000300 CPU ] 11 of 11 (100%) tests successful, 0 (0%) test skipped. Size of pool: 10240 Initial string: snek c1: 10, 20 c2: 30, 40 c3: 50, 60 Running test suite with seed 0x4e7eb250... get_full_greeting/test_basic_greeting[ OK ] [ 0.00000500 / 0.00000500 CPU ] get_full_greeting/test_short_buffer [ OK ] [ 0.00000400 / 0.00000400 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x98ffe6c3... allocate_scalar_array/test_allocate_scalar_array_size[ OK ] [ 0.00000600 / 0.00000600 CPU ] allocate_scalar_array/test_allocate_scalar_array_values[ OK ] [ 0.00000300 / 0.00000400 CPU ] allocate_scalar_array/test_allocate_scalar_array_zero_multiplier[ OK ] [ 0.00000500 / 0.00000500 CPU ] allocate_scalar_array/test_allocate_too_much[ OK ] [ 0.00001800 / 0.00001800 CPU ] 4 of 4 (100%) tests successful, 0 (0%) test skipped. Allocated 500 lists Running test suite with seed 0xd142494f... /example/compare [ OK ] [ 0.00000600 / 0.00000500 CPU ] /example/rand [ OK ] [ 0.00000500 / 0.00000400 CPU ] /example/parameters foo=one, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=one, bar=green [ OK ] [ 0.00000600 / 0.00000700 CPU ] foo=one, bar=blue [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=two, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=two, bar=green [ OK ] [ 0.00000400 / 0.00000300 CPU ] foo=two, bar=blue [ OK ] [ 0.00000500 / 0.00000600 CPU ] foo=three, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=three, bar=green [ OK ] [ 0.00000600 / 0.00000500 CPU ] foo=three, bar=blue [ OK ] [ 0.00001100 / 0.00001100 CPU ] 11 of 11 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x3b94faee... allocate_list/create [ OK ] [ 0.00000500 / 0.00000600 CPU ] allocate_list/overwrite [ OK ] [ 0.00000300 / 0.00000300 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x30623318... create_token_pointer_array/test_create_token_pointer_array_single[ OK ] [ 0.00000600 / 0.00000500 CPU ] create_token_pointer_array/test_create_token_pointer_array_multiple[ OK ] [ 0.00000600 / 0.00000700 CPU ] create_token_pointer_array/test_create_token_pointer_array_memory_allocation[ OK ] [ 0.00000600 / 0.00000600 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xdb4dc3bb... snek_zero_out/test_zero_out_integer [ OK ] [ 0.00000500 / 0.00000500 CPU ] snek_zero_out/test_zero_out_float [ OK ] [ 0.00000300 / 0.00000300 CPU ] snek_zero_out/test_zero_out_bool [ OK ] [ 0.00000300 / 0.00000300 CPU ] snek_zero_out/test_zero_out_nonzero_values[ OK ] [ 0.00000400 / 0.00000400 CPU ] 4 of 4 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x1e23c270... void-pointer/swap_ints [ OK ] [ 0.00000500 / 0.00000400 CPU ] void-pointer/swap_ints_same [ OK ] [ 0.00000300 / 0.00000300 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x343e18c2... void-pointer/swap_str [ OK ] [ 0.00000400 / 0.00000500 CPU ] void-pointer/test_swap_str_long [ OK ] [ 0.00000400 / 0.00000400 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x349b3cc2... swap/generic_ints [ OK ] [ 0.00000500 / 0.00000400 CPU ] swap/generic_strings [ OK ] [ 0.00000500 / 0.00000500 CPU ] swap/generic_struct [ OK ] [ 0.00000600 / 0.00000600 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xcc7f57e3... snekstack/create_stack_small [ OK ] [ 0.00000600 / 0.00000600 CPU ] snekstack/create_stack_large [ OK ] [ 0.00000500 / 0.00000500 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xb54c2f05... snekstack/create_stack [ OK ] [ 0.00000500 / 0.00000500 CPU ] snekstack/push_stack [ OK ] [ 0.00000700 / 0.00000600 CPU ] snekstack/push_double_capacity [ OK ] [ 0.00000900 / 0.00000900 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x986e20e8... snekstack/create_stack [ OK ] [ 0.00000500 / 0.00000500 CPU ] snekstack/push_stack [ OK ] [ 0.00000600 / 0.00000600 CPU ] snekstack/pop_stack [ OK ] [ 0.00000600 / 0.00000700 CPU ] snekstack/pop_stack_empty [ OK ] [ 0.00000600 / 0.00000600 CPU ] 4 of 4 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xf45ae006... snekstack/create_stack [ OK ] [ 0.00000700 / 0.00000600 CPU ] snekstack/push_stack [ OK ] [ 0.00000600 / 0.00000500 CPU ] snekstack/pop_stack [ OK ] [ 0.00000700 / 0.00000700 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xf83a103b... snekstack/heterogenous_stack [ OK ] [ 0.00000600 / 0.00000500 CPU ] 1 of 1 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x53a94d13... snekstack/multiple_types_stack [ OK ] [ 0.00000800 / 0.00000800 CPU ] 1 of 1 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xd977a296... object-integer-def/integer_constant [ OK ] [ 0.00000400 / 0.00000400 CPU ] object-integer-def/integer_obj [ OK ] [ 0.00000500 / 0.00000500 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x9850a5b5... object-integer/positive [ OK ] [ 0.00000600 / 0.00000500 CPU ] object-integer/zero [ OK ] [ 0.00000400 / 0.00000300 CPU ] object-integer/negative [ OK ] [ 0.00000400 / 0.00000300 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x06edb0c3... object-float/positive [ OK ] [ 0.00000600 / 0.00000400 CPU ] object-float/zero [ OK ] [ 0.00002200 / 0.00001700 CPU ] object-float/negative [ OK ] [ 0.00000300 / 0.00000300 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x846fed7d... object-string/copies_value [ OK ] [ 0.00000600 / 0.00000500 CPU ] 1 of 1 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x53cf4c00... object-vector/returns_null [ OK ] [ 0.00000600 / 0.00000600 CPU ] object-vector/multiple_objects [ OK ] [ 0.00000700 / 0.00000700 CPU ] object-vector/same_object [ OK ] [ 0.00000500 / 0.00000500 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x58fd8016... object-array/empty [ OK ] [ 0.00000500 / 0.00000500 CPU ] object-array/calloc [ OK ] [ 0.00000300 / 0.00000400 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x7f5412f2... object-array/set_and_get [ OK ] [ 0.00000500 / 0.00000500 CPU ] object-array/set_outside [ OK ] [ 0.00000600 / 0.00000600 CPU ] object-array/get_outside [ OK ] [ 0.00000500 / 0.00000400 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xa5a5383d... object-length/integer [ OK ] [ 0.00000600 / 0.00000600 CPU ] object-length/float [ OK ] [ 0.00000600 / 0.00000600 CPU ] object-length/string [ OK ] [ 0.00000600 / 0.00000600 CPU ] object-length/vector [ OK ] [ 0.00000400 / 0.00000300 CPU ] object-length/array [ OK ] [ 0.00000500 / 0.00000500 CPU ] 5 of 5 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x2e6f75bf... /example/compare [ OK ] [ 0.00000600 / 0.00000400 CPU ] /example/rand [ OK ] [ 0.00000500 / 0.00000500 CPU ] /example/parameters foo=one, bar=red [ OK ] [ 0.00000500 / 0.00000500 CPU ] foo=one, bar=green [ OK ] [ 0.00000500 / 0.00000600 CPU ] foo=one, bar=blue [ OK ] [ 0.00000900 / 0.00000800 CPU ] foo=two, bar=red [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=two, bar=green [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=two, bar=blue [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=three, bar=red [ OK ] [ 0.00000300 / 0.00000300 CPU ] foo=three, bar=green [ OK ] [ 0.00000300 / 0.00000400 CPU ] foo=three, bar=blue [ OK ] [ 0.00000400 / 0.00000300 CPU ] 11 of 11 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xdf462866... refcounttest_int_has_refcount [ OK ] [ 0.00000500 / 0.00000400 CPU ] refcounttest_float_has_refcount [ OK ] [ 0.00000500 / 0.00000400 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x3b906f5c... refcount/test_inc_refcount [ OK ] [ 0.00000600 / 0.00000600 CPU ] refcount/test_inc_refcount_more [ OK ] [ 0.00000400 / 0.00000400 CPU ] refcount/test_null_obj [ OK ] [ 0.00000500 / 0.00000500 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x6b51ea68... refcount/has_refcount [ OK ] [ 0.00000600 / 0.00000600 CPU ] refcount/inc_refcount [ OK ] [ 0.00000400 / 0.00000300 CPU ] refcount/dec_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] refcount/free_refcount [ OK ] [ 0.00000400 / 0.00000500 CPU ] refcount/string_freed [ OK ] [ 0.00000500 / 0.00000600 CPU ] 5 of 5 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xfcdf2928... refcount/has_refcount [ OK ] [ 0.00000600 / 0.00000500 CPU ] refcount/inc_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] refcount/dec_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] refcount/free_refcount [ OK ] [ 0.00000300 / 0.00000300 CPU ] refcount/string_freed [ OK ] [ 0.00000300 / 0.00000300 CPU ] refcount/vector3 [ OK ] [ 0.00000400 / 0.00000400 CPU ] refcount/vector3-same [ OK ] [ 0.00000300 / 0.00000200 CPU ] 7 of 7 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x2df34e21... refcount/array_set [ OK ] [ 0.00000800 / 0.00000800 CPU ] refcount/array_free [ OK ] [ 0.00000600 / 0.00000700 CPU ] refcount/has_refcount [ OK ] [ 0.00000300 / 0.00000300 CPU ] refcount/inc_refcount [ OK ] [ 0.00000400 / 0.00000400 CPU ] refcount/dec_refcount [ OK ] [ 0.00000400 / 0.00000300 CPU ] refcount/free_refcount [ OK ] [ 0.00000500 / 0.00000500 CPU ] refcount/string_freed [ OK ] [ 0.00000500 / 0.00000500 CPU ] refcount/vector3 [ OK ] [ 0.00000400 / 0.00000400 CPU ] 8 of 8 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x91892c1e... /example/compare [ OK ] [ 0.00000500 / 0.00000500 CPU ] /example/rand [ OK ] [ 0.00000600 / 0.00000500 CPU ] /example/parameters foo=one, bar=red [ OK ] [ 0.00000500 / 0.00000400 CPU ] foo=one, bar=green [ OK ] [ 0.00000500 / 0.00000500 CPU ] foo=one, bar=blue [ OK ] [ 0.00001100 / 0.00001200 CPU ] foo=two, bar=red [ OK ] [ 0.00000500 / 0.00000600 CPU ] foo=two, bar=green [ OK ] [ 0.00000600 / 0.00000600 CPU ] foo=two, bar=blue [ OK ] [ 0.00000300 / 0.00000400 CPU ] foo=three, bar=red [ OK ] [ 0.00000300 / 0.00000400 CPU ] foo=three, bar=green [ OK ] [ 0.00000400 / 0.00000400 CPU ] foo=three, bar=blue [ OK ] [ 0.00000400 / 0.00000300 CPU ] 11 of 11 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x0dddaf2c... refcount/correctly_free [ OK ] [ 0.00000700 / 0.00000700 CPU ] 1 of 1 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x435b0c66... mark-and-sweep/vm [ OK ] [ 0.00000600 / 0.00000700 CPU ] mark-and-sweep/vm [ OK ] [ 0.00001400 / 0.00000700 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x85af19f7... mark-and-sweep/test_vm_new [ OK ] [ 0.00000800 / 0.00000700 CPU ] mark-and-sweep/test_vm_new_frame [ OK ] [ 0.00000700 / 0.00000600 CPU ] mark-and-sweep/test_frames_are_freed [ OK ] [ 0.00000600 / 0.00000600 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x1cceaa41... mark-and-sweep/test_vm_new [ OK ] [ 0.00000800 / 0.00000700 CPU ] mark-and-sweep/test_frames_are_freed [ OK ] [ 0.00000700 / 0.00000700 CPU ] mark-and-sweep/test_new_object [ OK ] [ 0.00000700 / 0.00000600 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xc169d14b... mark-and-sweep/test_reference_object [ OK ] [ 0.00000700 / 0.00000700 CPU ] mark-and-sweep/test_frames_are_freed [ OK ] [ 0.00000700 / 0.00000700 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xac37539a... mark-and-sweep/test_one_ref [ OK ] [ 0.00000900 / 0.00000900 CPU ] mark-and-sweep/test_multi_ref [ OK ] [ 0.00000800 / 0.00000800 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0xaa6df145... mark-and-sweep/test_field_exists [ OK ] [ 0.00000900 / 0.00000800 CPU ] mark-and-sweep/test_marked_is_false [ OK ] [ 0.00000600 / 0.00000500 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x22d87982... mark-and-sweep/test_single_frame [ OK ] [ 0.00000900 / 0.00000900 CPU ] mark-and-sweep/test_multi_frame [ OK ] [ 0.00001000 / 0.00001100 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x147d09b4... mark-and-sweep/test_trace_vector [ OK ] [ 0.00000900 / 0.00000900 CPU ] mark-and-sweep/test_trace_array [ OK ] [ 0.00001200 / 0.00001300 CPU ] mark-and-sweep/test_trace_nested [ OK ] [ 0.00001700 / 0.00001700 CPU ] 3 of 3 (100%) tests successful, 0 (0%) test skipped. Running test suite with seed 0x93c96b1a... mark-and-sweep/test_simple [ OK ] [ 0.00000900 / 0.00000800 CPU ] mark-and-sweep/test_full [ OK ] [ 0.00001900 / 0.00002000 CPU ] 2 of 2 (100%) tests successful, 0 (0%) test skipped. [100%] Built target run #+END_SRC