Problem p01482 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#ifdef _MSC_VER
#define __typeof__ decltype
template <class T> int __builtin_popcount(T n) {
  return n ? 1 + __builtin_popcount(n & (n - 1)) : 0;
}
#endif

#define foreach(it, c)                                                         \\
  for (__typeof__((c).begin()) it = (c).begin(); it != (c).end(); ++it)
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define CLEAR(arr, val) memset(arr, val, sizeof(arr))

#define rep(i, n) for (int i = 0; i < n; ++i)

template <class T> void max_swap(T &a, const T &b) { a = max(a, b); }
template <class T> void min_swap(T &a, const T &b) { a = min(a, b); }

typedef long long ll;
typedef pair<int, int> pint;

const double EPS = 1e-8;
const double PI = acos(-1.0);
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};
bool valid_pos(int x, int y, int w, int h) {
  return 0 <= x && x < w && 0 <= y && y < h;
}

typedef int Ref;
const Ref NULL_REF = -810;
const Ref FREE_REF = 0;

vector<int> heap_blocks;
int using_size;
int limit_size;

int var_ref_table[256];

bool error = false;

string s;
int p;

void init() {
  heap_blocks.push_back(0);
  for (int i = 'A'; i <= 'Z'; ++i)
    var_ref_table[i] = FREE_REF;
}
void free_referenced_blocks() {
  for (int i = 'A'; i <= 'Z'; ++i) {
    Ref ref = var_ref_table[i];
    if (ref != NULL_REF && heap_blocks[ref] > 0) {
      using_size -= heap_blocks[ref];
      heap_blocks[ref] = 0;
    }
  }
}

Ref OS_malloc(int alloc_size) {
  if (using_size + alloc_size <= limit_size) {
    using_size += alloc_size;
    heap_blocks.push_back(alloc_size);
    return heap_blocks.size() - 1;
  } else
    return NULL_REF;
}
Ref OS_clone(Ref ref) {
  if (ref == NULL_REF)
    return NULL_REF;
  else {
    if (heap_blocks[ref] == 0) {
      error = true;
      return NULL_REF;
    }

    return OS_malloc(heap_blocks[ref]);
  }
}
void OS_free(Ref ref) {
  if (ref != NULL_REF) {
    if (heap_blocks[ref] == 0) {
      error = true;
      return;
    }

    using_size -= heap_blocks[ref];
    heap_blocks[ref] = 0;
  }
}
namespace Parser {
Ref expr();
Ref assign();
Ref malloc();
Ref clone();
Ref variable();
int number();

// <expr> ::= "(" <expr> ")" | <assign> | "NULL" | <variable> | <malloc> |
// <clone>
Ref expr() {
  if (s[p] == '(') {
    ++p;
    Ref res = expr();
    ++p;

    return res;
  } else if (s[p + 1] == '=')
    return assign();
  else if (s[p] == 'm')
    return malloc();
  else if (s[p] == 'c')
    return clone();
  else if (s[p] == 'N' && s[p + 1] == 'U') {
    p += 4;
    return NULL_REF;
  } else if (isupper(s[p]))
    return variable();
  else {
    cout << "Parse Error" << endl;
    exit(1);
  }
}

// <assign> ::= <variable> "=" <expr>
Ref assign() {
  char var = s[p];
  p += 2;

  return var_ref_table[var] = expr();
}

// <malloc> ::= "malloc(" <number> ")"
Ref malloc() {
  p += 7;
  int alloc_size = number();
  ++p;

  return OS_malloc(alloc_size);
}

// clone ::= "clone(" <expr> ")"
Ref clone() {
  p += 6;
  Ref ref = expr();
  ++p;

  return OS_clone(ref);
}

// <variable> ::= "A" | "B" | (ry
Ref variable() {
  char var = s[p];
  ++p;

  return var_ref_table[var];
}

// <number> ::= (ry
Ref number() {
  int res = 0;
  while (isdigit(s[p])) {
    res = res * 10 + (s[p] - '0');
    ++p;
  }
  return res;
}

// <free> ::= "free(" <expr> ")"
void free() {
  p += 5;
  Ref ref = expr();
  ++p;

  OS_free(ref);
}
}; // namespace Parser

int main() {
  ios::sync_with_stdio(false);

  cin >> limit_size;
  init();
  while (cin >> s) {
    s += '@';
    p = 0;

    if (s[p] == 'f')
      Parser::free();
    else
      Parser::expr();

    if (error) {
      cout << "Error" << endl;
      return 0;
    }
  }

  free_referenced_blocks();
  cout << using_size << endl;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

#ifdef _MSC_VER
#define __typeof__ decltype
template <class T> int __builtin_popcount(T n) {
  return n ? 1 + __builtin_popcount(n & (n - 1)) : 0;
}
#endif

#define foreach(it, c)                                                         \\
  for (__typeof__((c).begin()) it = (c).begin(); it != (c).end(); ++it)
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define CLEAR(arr, val) memset(arr, val, sizeof(arr))

#define rep(i, n) for (int i = 0; i < n; ++i)

template <class T> void max_swap(T &a, const T &b) { a = max(a, b); }
template <class T> void min_swap(T &a, const T &b) { a = min(a, b); }

typedef long long ll;
typedef pair<int, int> pint;

const double EPS = 1e-8;
const double PI = acos(-1.0);
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};
bool valid_pos(int x, int y, int w, int h) {
  return 0 <= x && x < w && 0 <= y && y < h;
}

typedef int Ref;
const Ref NULL_REF = -810;
const Ref FREE_REF = 0;

vector<int> heap_blocks;
int using_size;
int limit_size;

int var_ref_table[256];

bool error = false;

string s;
int p;

void init() {
  heap_blocks.push_back(0);
  for (int i = 'A'; i <= 'Z'; ++i)
    var_ref_table[i] = FREE_REF;
}
void free_referenced_blocks() {
  for (int i = 'A'; i <= 'Z'; ++i) {
    Ref ref = var_ref_table[i];
    if (ref != NULL_REF && heap_blocks[ref] > 0) {
      using_size -= heap_blocks[ref];
      heap_blocks[ref] = 0;
    }
  }
}

Ref OS_malloc(int alloc_size) {
  if (using_size + alloc_size <= limit_size) {
    using_size += alloc_size;
    heap_blocks.push_back(alloc_size);
    return heap_blocks.size() - 1;
  } else
    return NULL_REF;
}
Ref OS_clone(Ref ref) {
  if (ref == NULL_REF)
    return NULL_REF;
  else {
    if (heap_blocks[ref] == 0) {
      error = true;
      return NULL_REF;
    }

    return OS_malloc(heap_blocks[ref]);
  }
}
void OS_free(Ref ref) {
  if (ref != NULL_REF) {
    if (heap_blocks[ref] == 0) {
      error = true;
      return;
    }

    using_size -= heap_blocks[ref];
    heap_blocks[ref] = 0;
  }
}
namespace Parser {
Ref expr();
Ref assign();
Ref malloc();
Ref clone();
Ref variable();
int number();

// <expr> ::= "(" <expr> ")" | <assign> | "NULL" | <variable> | <malloc> |
// <clone>
Ref expr() {
  if (s[p] == '(') {
    ++p;
    Ref res = expr();
    ++p;

    return res;
  } else if (s[p + 1] == '=')
    return assign();
  else if (s[p] == 'm')
    return malloc();
  else if (s[p] == 'c')
    return clone();
  else if (s[p] == 'N' && s[p + 1] == 'U') {
    p += 4;
    return NULL_REF;
  } else if (isupper(s[p]))
    return variable();
  else {
    cout << "Parse Error" << endl;
    exit(1);
  }
}

// <assign> ::= <variable> "=" <expr>
Ref assign() {
  char var = s[p];
  p += 2;

  return var_ref_table[var] = expr();
}

// <malloc> ::= "malloc(" <number> ")"
Ref malloc() {
  p += 7;
  int alloc_size = number();
  ++p;

  return OS_malloc(alloc_size);
}

// clone ::= "clone(" <expr> ")"
Ref clone() {
  p += 6;
  Ref ref = expr();
  ++p;

  return OS_clone(ref);
}

// <variable> ::= "A" | "B" | (ry
Ref variable() {
  char var = s[p];
  ++p;

  return var_ref_table[var];
}

// <number> ::= (ry
Ref number() {
  int res = 0;
  while (isdigit(s[p])) {
    res = res * 10 + (s[p] - '0');
    ++p;
  }
  return res;
}

// <free> ::= "free(" <expr> ")"
void free() {
  p += 5;
  Ref ref = expr();
  ++p;

  OS_free(ref);
}
}; // namespace Parser

int main() {
  ios::sync_with_stdio(false);

  freopen("C:\\\\Users\\\\Petit\\\\Desktop\\\\tete\\\\Debug\\\\input.txt", "r", stdin);

  cin >> limit_size;
  init();
  while (cin >> s) {
    s += string(10, '@');
    p = 0;

    if (s[p] == 'f')
      Parser::free();
    else
      Parser::expr();

    if (error) {
      cout << "Error" << endl;
      return 0;
    }
  }

  free_referenced_blocks();
  cout << using_size << endl;
}