← Back to All Tutors

Tutor Profile

Marcus Weber

MS Computer Science from EPFL Lausanne. Specializes in C memory management and C++ RAII and modern ownership patterns.

Marcus Weber profile card with credential MS Computer Science and 980+ assignments delivered
980+ Assignments Delivered Across CSHH and prior tutoring
6 Years Tutoring Since first paid teaching role
3 Languages Covered C, C++, Java
8 Documented Specialties Each with a diagnostic playbook

About the Tutor

About Marcus

Marcus finished his CS masters at EPFL, then spent four years writing systems software for a high-frequency trading desk before he started tutoring full time. The kernel-bypass networking stack, the lock-free ring buffers, the cache-line-aligned struct layouts. The work was relentless on memory discipline, which is exactly the discipline most undergraduate C and C++ assignments are trying to teach. He moved to tutoring after a sabbatical year, kept the rigor, and dropped the production-fire stress. 980+ CSHH assignments and six years later, students still get the trading-desk debugger workflow whether they asked for it or not.

His specialty is the class of bugs that students cannot reproduce in their own debugger. Segfaults that only appear with optimization enabled. Heap corruption that surfaces three function calls after the actual overrun. Race conditions in pthreads code that pass 99 times and fail the hundredth on the autograder. He keeps a documented Valgrind workflow for each: --tool=memcheck with --track-origins=yes for use-after-free, --tool=helgrind for the thread race, --tool=cachegrind when the question is performance instead of correctness. Students who watch him work the toolchain start to recognize the failure modes by signature.

A representative case from earlier this year. A CS61C student submitted a multi-threaded matrix multiplication that passed all functional tests but ran 40% slower than the staff reference on the performance autograder. The student suspected the OpenMP scheduling. Marcus ran the binary under cachegrind, identified that the inner loop was thrashing the L1 cache because the matrix had been stored row-major and accessed column-major. The fix was eight lines: transpose the second matrix before the multiply, eat the O(n^2) transpose cost to win back O(n^3) cache hits. Score went from 60% to 100% on the next submission. The student understood why because Marcus walked through the cache-miss numbers cachegrind printed line by line.

On the C side his teaching pattern is to make memory ownership explicit before writing any code. Every malloc has a named owner, every owner has a free in the corresponding cleanup path, every function signature documents whether it takes ownership of its arguments or borrows them. Students who learn this discipline stop writing memory leaks because the leak is visible in the function signature before the code runs. C++ students get the same treatment with RAII: every resource is owned by an object, ownership transfers happen at construction or with std::move, and naked new is a code smell that needs justification.

The concurrency work is where most C and C++ students lose their footing. Marcus walks them through a concrete model before any code: shared memory, threads of execution, the happens-before relation, the difference between data race and race condition. Then he picks a textbook bug, a counter incremented from two threads without a mutex, and shows it in three forms. The C source. The compiler-generated assembly with the load, add, store sequence visible. The thread-sanitizer output flagging the race. Students see why the race exists at the instruction level, not just at the C level. The next mutex they write goes in the right place.

His CSHH workflow leans heavily on reproducing the failure before patching it. The brief arrives, he reads the autograder spec first, compiles the student starter code with -Wall -Wextra -Werror -fsanitize=address,undefined, and runs it against the rubric inputs. Bugs that surface under sanitizers but not under a clean compile are almost always the source of the failing test. He sends back a patched solution plus a short writeup explaining what the sanitizer caught and how to read the trace next time. Students who keep the writeup learn to find their own bugs the following week, which is the actual goal of the exercise even when the immediate need is the failing autograder.

Documented Specialties

What Marcus Specializes In

C memory management

Malloc/free discipline, valgrind traces.

C++ RAII and modern ownership patterns

Unique_ptr, shared_ptr, move semantics.

pthreads concurrency

Mutex, condvar, rwlock, race-condition isolation.

GDB and LLDB workflow

Backtrace, watchpoints, conditional breakpoints.

AddressSanitizer and UndefinedBehaviorSanitizer interpretation

Marcus handles addresssanitizer and undefinedbehaviorsanitizer interpretation as a recurring CSHH workload, with documented patterns and reference solutions.

CMake build configuration

Marcus handles cmake build configuration as a recurring CSHH workload, with documented patterns and reference solutions.

Sample Reviewed Code

Code Marcus Has Reviewed

A representative snippet from Marcus's workflow. Pulled from the diagnostic playbook Marcus runs on incoming CSHH assignments in this language.

C matmul_cache_friendly.c

          
          // Transpose B before the inner loop so the inner stride hits
        
          
          // L1 cache lines instead of striding by N. CS61C perf lab: 60% -> 100%.
        
          
          // Cost: O(n^2) transpose to save O(n^3) cache misses. Net win at n >= 64.
        
          
           
        
          
          void matmul(const double *A, const double *B, double *C, size_t n) {
        
          
              double *BT = aligned_alloc(64, n * n * sizeof(double));
        
          
              for (size_t i = 0; i < n; i++)
        
          
                  for (size_t j = 0; j < n; j++)
        
          
                      BT[j * n + i] = B[i * n + j];  // B^T, row-major
        
          
           
        
          
              for (size_t i = 0; i < n; i++)
        
          
                  for (size_t j = 0; j < n; j++) {
        
          
                      double acc = 0.0;
        
          
                      for (size_t k = 0; k < n; k++)
        
          
                          acc += A[i * n + k] * BT[j * n + k]; // both sequential
        
          
                      C[i * n + j] = acc;
        
          
                  }
        
          
              free(BT);
        
          
          }
        

Coverage Map

Subjects and Languages Marcus Covers

Course Matches

Courses Marcus Specializes In

6.006 Massachusetts Institute of Technology

MIT 6.006: Introduction to Algorithms

MIT 6.006 introduces algorithms across 13 weeks with 26 lectures, 13 recitations, and 7 problem sets. The Spring 2020 redesign by Erik Demaine, Jason Ku, and Justin Solomon...

8 recurring assignments covered

Get help with 6.006

FAQ

Frequently Asked Questions

A segfault appears only with -O2 but not with -O0. Where do you start?
Undefined behavior somewhere the optimizer noticed and exploited. Compile with -fsanitize=undefined and rerun. Common culprits: signed integer overflow that -O0 happened to compute correctly, a strict-aliasing violation that the optimizer reordered, or a use of an uninitialized stack variable that -O0 happened to zero-pad. UBSan will name the file and line in most cases.
How do you teach pointer arithmetic without losing the student?
Draw the address space on paper before writing any code. Box per byte, arrow per pointer, value per box. Then write three lines of code and ask the student to update the diagram. Pointer arithmetic is a spatial skill before it is a syntactic one. Students who skip the diagram stage memorize the syntax and lose it within a week.
When is std::shared_ptr the wrong choice in C++?
When ownership is actually unique. shared_ptr carries an atomic reference count on every copy and destruction, which is a real cost in hot paths. If the resource has one owner and the rest are observers, use unique_ptr and pass raw pointers or references to the observers. Default to unique_ptr; reach for shared_ptr only when the lifetime is genuinely shared across owners.
What is your Valgrind invocation for a heap-corruption bug?
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes ./your-binary. The track-origins flag is the important one; it tells you where the uninitialized value originated, not just where it got read. Slower by 2x but worth the wait when the bug is otherwise non-reproducible.
Do you cover the autograder format for CS61C, CMU 15-213, or similar systems courses?
Yes. The CS61C autograder runs against specific test inputs with specific compiler flags; the CMU 15-213 lab autograder uses driver.pl with a known set of trace files. I match the exact compilation flags and test invocation patterns the course uses, then validate the solution against the same harness before delivery.
How do you handle a race condition that only appears under load?
Helgrind first to identify the unsynchronized access, then targeted thread-sanitizer (-fsanitize=thread) for the stack traces. Reproducing under load usually means the timing window is microseconds wide; the tooling forces the window open by inserting synchronization checks at every shared-memory access. Slow, but it finds the bug deterministically.

Work With Marcus?

Submit your assignment with Marcus in mind. We will route the request to the best-fit tutor based on subject, language, and current load. Average first reply inside 30 minutes during business hours.

Submit for Marcus