#include #include // Finding three bugs // // The following program contains three errors, // each involving dynamically allocated memory // or accessing an array. // // Find all three errors. For each one: // // 1. Identify the incorrect statement. // 2. Explain why it is incorrect. // 3. Correct the statement. // // Compile the program with warnings enabled: // // g++ -std=c++17 -Wall -Wextra -pedantic // // Some errors may produce compiler warnings, // while others may compile without any warning. // // After identifying the errors, correct the // program and verify that it runs properly. // Function declarations void initialize_array( double array[], std::size_t const capacity, double const value ); int main(); // Function definitions int main() { double *a_data{ new double[10] }; initialize_array( a_data, 10, 3.14 ); delete a_data; a_data = nullptr; // What should happen if a null pointer // is passed to initialize_array(...)? initialize_array( a_data, 10, 3.14 ); return 0; } // Set every entry in the array to value. // // If array is nullptr, do nothing. void initialize_array( double array[], std::size_t const capacity, double const value ) { if ( array == nullptr ) { array[0] = 0.0; } else { for ( std::size_t k{ 0 }; k <= capacity; ++k ) { array[k] = value; } } } // Hint: // // Consider these three questions: // // 1. What happens when an attempt is made // to access array[0] if array is nullptr? // // 2. If an array has a capacity of 10, // what are its valid indices? // // 3. What is the correct way to release // memory allocated using new[]? // // You may also try compiling with // AddressSanitizer: // // g++ -std=c++17 -Wall -Wextra -pedantic \ // -g -fsanitize=address,undefined \ // -fno-omit-frame-pointer main.cpp // // AddressSanitizer can help detect invalid // memory accesses and mismatched allocation // and deallocation. // Here are the three errors: // // // 1. Dereferencing a null pointer // // if ( array == nullptr ) { // array[0] = 0.0; // } // // If array is nullptr, there is no array // to access. Evaluating array[0] causes // undefined behavior. // // Since the function should do nothing // when given a null pointer, replace // this statement with: // // if ( array == nullptr ) { // return; // } // // // 2. Accessing beyond the end of an array // // for ( std::size_t k{ 0 }; // k <= capacity; // ++k ) // // An array with capacity entries has // valid indices from 0 through capacity - 1. // // When k == capacity, array[k] is outside // the array. // // The condition must therefore be: // // k < capacity // // // 3. Incorrectly deallocating an array // // delete a_data; // // Memory allocated using new[] must be // released using delete[]. // // The correct statement is: // // delete[] a_data; // // A compiler may warn about this mismatch, // but a warning is not guaranteed. // Here is the corrected program: /* #include #include void initialize_array( double array[], std::size_t const capacity, double const value ); int main() { double *a_data{ new double[10] }; initialize_array( a_data, 10, 3.14 ); delete[] a_data; a_data = nullptr; // This call is now safe. The function // detects nullptr and immediately returns. initialize_array( a_data, 10, 3.14 ); return 0; } void initialize_array( double array[], std::size_t const capacity, double const value ) { if ( array == nullptr ) { return; } for ( std::size_t k{ 0 }; k < capacity; ++k ) { array[k] = value; } } */