Garbage collection works only for memory. It does not work for other resources because it is generally not deterministic.
All GC languages have (some got at a later point) language constructs to allow deterministic resource management.
with open('file.txt') as file:
for line in file:
pass
// `IDisposable` interface
using (Font font1 = new Font("Arial", 10.0f))
{
byte charset = font1.GdiCharSet;
}
func Contents(filename string) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close() // f.Close will run when we're finished.
Automatic variable is allocated and deallocated when the program flow enters and leaves the variable's context.
Variable's context is the scope of its declaration
void function() {
std::ifstream f("input.txt");
} // f is destroyed here
void function() {
// ...
{
std::ifstream f("input.txt");
} // f is destroyed here
// ...
}
// loading ...
// loading ...
void function()
{
if (int x = rand()) {
std::cout << x << std::endl;
} else {
std::cout << "random 0" << std::endl;
} // x is destroyed here
}
class Logger
{
private:
std::ifstream input;
};
// input gets created when a Logger instance gets created
// input gets destroyed when the instance is destroyed
class Logger
{
private:
static std::ifstream input;
};
// input gets created sometime before executing main
// input gets destroyed sometime after main has finished
int main() {
}
std::ofstream input("input.txt");
// input gets created sometime before executing main
// input gets destroyed sometime after main has finished
void function() {
static std::ofstream input("input.txt");
// input gets created first time executing the function
}
// input gets destroyed sometime after main has finished
// ...
std::ifstream* input = new std::ifstream("input.txt");
// ...
delete input; // <-- input gets destroyed here
// loading ...
Lifetime: 0x7fffc7c7552f: lives
Lifetime: 0x7fffc7c7552f: dies
// loading ...
Lifetime: 0x7fffc7c7552e: lives
NeverMember: 0x7fffc7c7552e: is about to live
Lifetime: 0x7fffc7c7552e: dies
exception:not this time
// loading ...
Lifetime: 0x7fffc7c7552d: lives
NeverMember: 0x7fffc7c7552d: is about to live
Lifetime: 0x7fffc7c7552d: dies
exception:not this time
// loading ...
Lifetime: 0x7fffcbf05d67: lives
Reference to 0x7fffcbf05d67
Lifetime: 0x7fffcbf05d67: dies
// loading ...
Lifetime: 0x119d010: lives
Leaking: 0x7fff49285b00: lives
exception: it all goes wrong
bool HasEmbededNull(const char* file)
{
std::ifstream input(file, std::ios::binary);
while (input) {
if (input.get() == '\0') {
return true;
}
}
return false;
}
bool HasEmbededNull(const char* file)
{
auto input = std::fopen(file, "rb");
while (input && !feof(input)) {
if (fgetc(input) == '\0') {
return true;
}
}
fclose(input);
return false;
}
bool HasEmbededNull(const char* file)
{
auto input = std::fopen(file, "rb");
while (input && !feof(input)) {
if (fgetc(input) == '\0') {
fclose(input); // !!!!!!!!!!!
return true;
}
}
fclose(input);
return false;
}
ALWAYS manage resources following RAII!
NEVER STORE a resource by a plain pointer!