Skip to content

Environment is copyable but owns a raw Grid*, so copying it double-deletes the grid #44

Description

@dmccoystephenson

Environment owns a heap-allocated Grid through a raw pointer — grid = new Grid(id, size) in the constructor (src/environment.cpp:10) and delete grid in the destructor (src/environment.cpp:14) — but declares no copy constructor or copy-assignment operator (src/header/environment.h:14-15 declare only the constructor and destructor). The compiler therefore generates a shallow copy: two Environment objects end up holding the same Grid*, and the second one to be destroyed deletes an already-freed grid.

This is the same class of defect as #27 (a new/free mismatch in the destructor, fixed in #30): the destructor is now correct, but the object is still unsafe to copy. Any of the following triggers a double delete at scope exit:

Environment a(0, "Earth", 4);
Environment b = a;          // copy-construct: b.grid == a.grid
Environment a(0, "Earth", 4);
Environment b(1, "Mars", 4);
b = a;                      // copy-assign: b's original grid is leaked, then a.grid is deleted twice

Passing an Environment by value to a function, or storing one in a std::vector<Environment> that reallocates, does the same. Nothing in the current test suite copies an Environment, so the suite does not observe it, but run_tests_asan.sh would report it as a heap-use-after-free / double-free the moment such a test were added.

Suggested fix: delete the copy operations in the header, matching the existing Grid() = delete; style already used in src/header/grid.h:

Environment(const Environment&) = delete;
Environment& operator=(const Environment&) = delete;

This turns the runtime double-free into a compile error for any caller that copies. (Alternatively, Grid* grid could become std::unique_ptr<Grid>, which gives the same non-copyable semantics and removes the explicit delete; either approach is acceptable, the deleted-copy pair being the smaller change.) A characterization test cannot assert a compile error, so the acceptance criterion is a clean bash run_tests_asan.sh run plus the two deleted declarations being present in the header.

This issue body was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions