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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cerr << *i << " ";
  cerr << endl;
}
inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
class MemoryError {};

struct Result {
  int value, p;
  Result(int v, int p) : value(v), p(p) {}
};

int variable[30];
int memory[100001];
int memory_length;
const int MEMORY_MAX = 100000;
int HEAPSIZE; // 残り使用可能なメモリ量

int malloc_memory(int size) {
  if (HEAPSIZE >= size) {
    assert(memory_length >= 1 && memory_length < MEMORY_MAX);
    HEAPSIZE -= size;
    memory[memory_length++] = size;
    return memory_length - 1;
  } else {
    return 0; // NULL
  }
}

Result line(const string &s, int p);
Result expr(const string &s, int p);
Result assign(const string &s, int p);
Result malloc(const string &s, int p);
Result free(const string &s, int p);
Result clone(const string &s, int p);

Result line(const string &s, int p) {
  if (s.substr(p, 4) == "free") {
    return free(s, p);
  } else {
    return expr(s, p);
  }
}

Result expr(const string &s, int p) {
  if (s[p] == '(') {
    Result r = expr(s, p + 1);
    assert(s[r.p] == ')');
    r.p++;
    return r;
  } else if (s.substr(p, 4) == "NULL") {
    return Result(0, p + 4);
  } else if (s.substr(p, 6) == "malloc") {
    return malloc(s, p);
  } else if (s.substr(p, 5) == "clone") {
    return clone(s, p);
  } else if (isupper(s[p])) {
    if (s[p + 1] == '=') {
      Result r = expr(s, p + 2);
      variable[s[p] - 'A'] = r.value;
      return r;
    } else {
      return Result(variable[s[p] - 'A'], p + 1);
    }
  } else {
    assert(false);
  }
}

Result malloc(const string &s, int p) {
  assert(s.substr(p, 7) == "malloc(");
  p += 7;
  int size = 0;
  while (isdigit(s[p])) {
    size = size * 10 + s[p++] - '0';
  }
  assert(s[p] == ')');
  p++;
  int pointer = malloc_memory(size);
  return Result(pointer, p);
}

Result free(const string &s, int p) {
  assert(s.substr(p, 5) == "free(");
  p += 5;
  Result r = expr(s, p);
  assert(s[r.p] == ')');
  r.p++;
  if (memory[r.value] == -1) {
    throw MemoryError();
  } else if (memory[r.value] == 0) {
    // NULL
    return Result(0, r.p);
  } else {
    HEAPSIZE += memory[r.value];
    memory[r.value] = -1;
    return r;
  }
}

Result clone(const string &s, int p) {
  assert(s.substr(p, 6) == "clone(");
  p += 6;
  Result r = expr(s, p);
  assert(s[r.p] == ')');
  r.p++;
  if (memory[r.value] == -1) {
    throw MemoryError();
  } else if (memory[r.value] == 0) {
    // NULL
    return Result(0, r.p);
  } else {
    int pointer = malloc_memory(memory[r.value]);
    return Result(pointer, r.p);
  }
}

int main() {
  memset(memory, -1, sizeof(memory));
  memory_length = 1;
  memory[0] = 0;
  REP(i, 30) variable[i] = MEMORY_MAX;

  cin >> HEAPSIZE;
  string s;
  try {
    while (cin >> s) {
      line(s, 0);
    }
    REP(i, 30) memory[variable[i]] = 0;
    int ans = 0;
    REP(i, memory_length) if (memory[i] > 0) { ans += memory[i]; }
    cout << ans << endl;
  } catch (...) {
    cout << "Error" << endl;
  }

  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
// C++11
#if __cplusplus == 201103L
#include <tuple>
#endif

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cout << *i << " ";
  cout << endl;
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int N;
string s;
int p;
int u; // for used
int used[100000];
int pointer[26];
bool error;
void line();
int expr();
void free_s();
int malloc();
int clone();
int variable();
int num();
void line() {
  if (s[p] == 'f') {
    free_s();
  } else {
    expr();
  }
}
int expr() {
  if (s[p] == '(') {
    p += 1;
    int res = expr();
    p += 1;
    return res;
  } else if (s[p] == 'N' && s[p + 1] == 'U') {
    return 0;
  } else if (s[p] == 'm') {
    return malloc();
  } else if (s[p] == 'c') {
    return clone();
  } else if (s[p] >= 'A' && s[p] <= 'Z') {
    char var = s[p++];
    if (s[p] == '=') {
      p += 1;
      int secadr = expr();
      pointer[var - 'A'] = secadr;
    } else {
    }
    return pointer[var - 'A'];
  } else {
    printf("%d:%s\\n", p, s.c_str());
    assert(false);
  }
}
int malloc() {
  assert(p + 7 <= s.size() && s.substr(p, 7) == "malloc(");
  p += 7;
  int size = num();
  if (size > N)
    return 0;
  else
    N -= size;
  assert(s[p] == ')');
  p += 1;
  used[u++] = size;
  return u - 1;
}
void free_s() {
  assert(s.substr(p, 5) == "free(");
  p += 5;
  int e = expr();
  if (e == -1) {
    error = true;
    e = 0;
  }
  if (e == 0) {
  } else {
    N += used[e];
    used[e] = 0;
    REP(i, 26) if (pointer[i] == e) pointer[i] = -1;
  }
  assert(s[p] == ')');
  p += 1;
}
int clone() {
  assert(s.substr(p, 6) == "clone(");
  p += 6;
  int adr = expr();
  if (adr == -1) {
    error = true;
    adr = 0;
  }
  if (adr == 0) {
    return 0;
  }
  assert(s[p] == ')');
  p += 1;
  int size = used[adr];
  if (size > N)
    return 0;
  else
    N -= size;
  used[u++] = size;
  return u - 1;
}
int variable() {
  assert(s[p] >= 'A' && s[p] <= 'Z');
  return pointer[s[p++] - 'A'];
}
int num() {
  int res = 0;
  while (isdigit(s[p])) {
    res = res * 10 + s[p] - '0';
    p++;
  }
  return res;
}
int main() {
  while (cin >> N && N) {
    error = false;
    u = 1;
    memset(used, 0, sizeof(used));
    used[0] = 0;
    memset(pointer, -1, sizeof(pointer));
    cin.ignore();
    while (getline(cin, s) && s != "") {
      p = 0;
      line();
    }
    assert(used[0] == 0);
    REP(i, 26) if (pointer[i] != -1) used[pointer[i]] = 0;
    int res = 0;
    assert(u < 100000);
    REP(i, 100000) {
      assert(used[i] >= 0);
      res += used[i];
    }
    if (error)
      cout << "Error" << endl;
    else
      cout << res << endl;
  }
  return 0;
}