Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

C++ Module 15

Build systems, testing and tooling interview questions

Interview questions on build systems, testing and tooling: warm-ups, then what each harder question tests and how a good answer starts.

35 questions: 9 warm-ups and 26 with model answers · Levels: Fresher to staff

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher

    What is the difference between PRIVATE, PUBLIC and INTERFACE in target_link_libraries?

    Answered in the lesson CMake for C++: targets, properties and presets

  2. Fresher

    What is the difference between a static and a shared library in C++?

    Answered in the lesson Static and shared libraries in C++

  3. Fresher

    What is the difference between CTest and a test framework such as GoogleTest or Catch2?

    Answered in the lesson Unit tests with GoogleTest or Catch2 and CTest

  4. Fresher

    Why is adding a third-party library harder in C++ than in a language with one package manager, and what do vcpkg and Conan do about it?

    Answered in the lesson vcpkg and Conan: C++ dependency management

  5. Fresher

    Why do you compile with -O0 -g before stepping through a C++ program in a debugger?

    Answered in the lesson Debugging C++ with LLDB and GDB

  6. Fresher to mid

    Why do AddressSanitizer and ThreadSanitizer need separate builds?

    Answered in the lesson Sanitizer and hardened C++ build presets

  7. Fresher

    What is the difference between clang-format, clang-tidy and a static analyzer such as clang --analyze?

    Answered in the lesson clang-tidy, clang-format and static analysis

  8. Fresher to mid

    What is the difference between a sampling profiler and an instrumenting profiler?

    Answered in the lesson Profiling C++: finding where the time goes

  9. Fresher

    Why does long have 4 bytes on Windows but 8 bytes on 64-bit Linux and macOS?

    Answered in the lesson Portability across compilers, platforms and judges

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Fresher to mid

    A CMake project builds on your laptop, but a teammate's fresh clone fails: the app cannot find mathx/stats.hpp, a header of the project's own mathx library. That library's CMakeLists.txt calls include_directories(include), and you once ran make install for mathx. Explain both results and fix the CMake code.

    What it tests
    Directory-scoped versus target-scoped settings, usage requirements, how an installed copy of a header hides a missing dependency, and making the build reproducible.
    First step
    Compare the app's compile command on both machines, from compile_commands.json or cmake --build --verbose. include_directories() reaches only targets in the library's own folder and the folders below it, so the app's command has no -I for mathx on either machine. Your laptop finds the header anyway, in /usr/local/include, where make install copied it.
    Follow-ups

    From the lesson CMake for C++: targets, properties and presets

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  2. Mid to senior

    You added -Wall -Werror to CMAKE_CXX_FLAGS at the top of your CMakeLists.txt. Now a third-party library pulled in with FetchContent fails to build with GCC 16, on warnings in its own code that you cannot fix. Why, and how do you keep strict warnings on your code only?

    What it tests
    Global versus target-scoped flags, how FetchContent and add_subdirectory inherit settings, SYSTEM include folders, and where build-wide policy such as -Werror belongs.
    First step
    CMAKE_CXX_FLAGS set at the top is used for every C++ file of that folder and of every folder added below it, and FetchContent_MakeAvailable adds the library with add_subdirectory, so its sources get -Werror too. Move the warnings onto your own targets, for example an INTERFACE target that each of them links PRIVATE, and leave the library's flags alone.
    Follow-ups

    From the lesson CMake for C++: targets, properties and presets

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  3. Mid to senior

    Your macOS program runs from the build folder, but the zip you send to testers fails at start with "Library not loaded: @rpath/libgeo.dylib" and "Reason: no LC_RPATH's found". Explain what happened, and fix the build for macOS and Linux without asking testers to set any variable.

    What it tests
    How programs record and find shared libraries, the build-folder rpath that CMake adds and install removes, relative rpaths, and why environment variables are no fix.
    First step
    Run otool -L on the zipped program to see what it needs, and otool -l to see the folders it searches for @rpath. Then run both commands on the same program in the build folder, where it works, and compare: the difference between the two programs is the cause.
    Follow-ups

    From the lesson Static and shared libraries in C++

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  4. Mid to senior

    A bug-fix release of your shared library adds one field to a public struct. Programs built against the previous release, which nobody recompiled, now print wrong values but do not crash. Explain the mechanism, and how you would ship the change safely.

    What it tests
    Binary compatibility: layouts and calling conventions compiled into callers, which changes break the ABI, SOVERSION and so-names, and ways to change an interface without breaking it.
    First step
    The old programs were compiled with the old header, so they still assume the struct's old size and the old offsets of its fields. Compare the two versions of the public header, and ask what the unchanged programs read when the library hands them the new layout. No compiler or linker checks this for you.
    Follow-ups

    From the lesson Static and shared libraries in C++

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 4 minutes
  5. Senior to staff

    Your team ships a C++ SDK that other companies link into their apps on Windows, macOS and Linux. Should it be a static or a shared library? Defend the choice, and say what you would require from the users of the SDK either way.

    What it tests
    Static and shared delivery compared: size, updates, symbol clashes, the C++ ABI across compilers and standard libraries, Windows run-time libraries, and supporting other people's builds.
    First step
    Start from who controls the build: customers compile with their own compilers, standard libraries and settings. A C++ interface that passes std::string, containers or exceptions works only when both sides agree on the ABI, so decide the interface first, C++ or a C wrapper, and let the static or shared choice follow from it.
    Follow-ups

    From the lesson Static and shared libraries in C++

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  6. Mid to senior

    A GoogleTest test passes on every developer's machine but fails about once in 50 CI runs. Using CTest and the framework's own options, how do you find out whether the test or the code under test is at fault?

    What it tests
    Reproducing flaky tests: repetition, parallel and shuffled runs, shared state between tests, ThreadSanitizer, and deciding between a fix and a quarantine.
    First step
    Reproduce it before guessing. Run that one test many times with ctest --repeat until-fail:200 -R and its name, then the whole suite in parallel and in random order, with ctest -j 8 and --gtest_shuffle. A failure that needs other tests running points at shared state; one that appears alone points at the test or the code itself.
    Follow-ups

    From the lesson Unit tests with GoogleTest or Catch2 and CTest

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  7. Senior to staff

    A C++ suite of about 3,000 GoogleTest tests in 300 files takes 14 minutes in CI, most of it in the build. How would you make it faster without testing less?

    What it tests
    Where test time goes, compile cost per test file, precompiled headers, unity builds and caches, splitting test programs, parallel ctest, and keeping slow tests out of every pull request.
    First step
    Measure first: split the CI time into configure, build and ctest, and read the slowest tests in ctest's output. If the build dominates, the cost is the heavy framework headers compiled into each of 300 files and the links of large test programs, so attack compilation; if the run dominates, look at serial execution and a few slow tests.
    Follow-ups

    From the lesson Unit tests with GoogleTest or Catch2 and CTest

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  8. Mid to senior

    A function decides whether a cached file is stale by comparing its modification time with the current time. How do you unit-test it reliably, without sleeping and without depending on the real clock or disk?

    What it tests
    Designing code for tests: passing in the clock and the file system, fakes against mocks, gMock, and testing the boundary cases of time.
    First step
    Separate the decision from the effects. Let the function take the current time and the file's modification time as values, or a clock and a small file-system interface as parameters. Then each test passes fixed times and checks the boundaries, such as exactly at the expiry time, without touching the disk or waiting.
    Follow-ups

    From the lesson Unit tests with GoogleTest or Catch2 and CTest

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  9. Mid to senior

    A release build pulled a newer version of a dependency than the one QA tested, and a bug appeared in production. Design the dependency policy that makes every build reproducible, with vcpkg or with Conan.

    What it tests
    Version resolution, baselines, version ranges, lockfiles and recipe revisions, deliberate upgrades, binary caches and the checks CI needs.
    First step
    Find what was not pinned. With vcpkg, a manifest without a committed builtin-baseline, or a baseline updated by a script, lets versions move; with Conan, a version range or an exact version without a lockfile lets a new version or recipe revision in. The fix is a pin that is committed with the code and used by every build.
    Follow-ups

    From the lesson vcpkg and Conan: C++ dependency management

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  10. Senior to staff

    Before a release, the legal team asks which licences your app's 40 C++ dependencies carry and what you owe for each. How do you answer quickly and reliably, and what would make you stop the release?

    What it tests
    Getting licence data from the package managers, judging how far declared licences can be trusted, obligations by licence family, NOTICE files and policy checks in CI.
    First step
    Produce the list from the build, not from memory: conan graph info with the release profile and lockfile, or the licences and SPDX files vcpkg installs. Then compare every entry with an allowlist, and set aside each one you cannot classify for a closer look.
    Follow-ups

    From the lesson vcpkg and Conan: C++ dependency management

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  11. Senior to staff

    A team of five ships a desktop app on Windows, macOS and Linux with about 15 dependencies. CI takes 25 minutes, mostly building those dependencies from source on every run. Which dependency approach do you choose, and why?

    What it tests
    Comparing vcpkg, Conan, FetchContent and vendoring on platforms, binaries and caching, reproducibility, upkeep for a small team, and measuring before deciding.
    First step
    Measure what the 25 minutes are: if the dependencies are rebuilt because nothing is cached, any tool with a binary cache fixes most of it. Then weigh the platforms and the team: three systems and 15 libraries call for a real package manager with a cache, not FetchContent or vendored copies that someone must update by hand.
    Follow-ups

    From the lesson vcpkg and Conan: C++ dependency management

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  12. Mid to senior

    A crash dump comes from an -O2 build with debug information. In the crashing frame the debugger shows a loop index of 1, a pointer as optimised out, and a line in the middle of another function. Which of these do you trust, and how do you get reliable values without moving the whole build to -O0?

    What it tests
    How optimisation changes debug information (location lists, inlining, line tables) and which evidence in an optimised crash is a fact rather than the compiler's reconstruction.
    First step
    Separate facts from reconstructions. The faulting instruction, the registers and the return addresses of the backtrace are facts. Variable values and line numbers are what the debug information claims, and in optimised code that record can be partial or wrong. Start from the faulting instruction in the disassembly and check each printed value against the code that uses it.
    Follow-ups

    From the lesson Debugging C++ with LLDB and GDB

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  13. Fresher to mid

    A long-lived Order object's status field sometimes turns into Cancelled, although no code path should do that. Nothing crashes, and an AddressSanitizer build is clean. How do you find the code that writes the field, and what limits do you run into?

    What it tests
    Watchpoints on an address, hardware watchpoint limits, conditions, objects that move, and why a sanitizer cannot see a wrong but valid write.
    First step
    Reproduce it once under the debugger, stop just after the object is constructed, and put a watchpoint on the field. Each stop then shows the old value, the new value and the code that wrote it, so the first change you did not expect points at the culprit.
    Follow-ups

    From the lesson Debugging C++ with LLDB and GDB

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  14. Mid to senior

    A C++ service crashed overnight on a Linux server. You have a core file and the stripped release binary that was deployed. What do you need to get a backtrace with function names, lines and values, and what do you change so that the next crash is easy to debug?

    What it tests
    Separate debug information, build IDs, matching a binary to a core, the kernel's core settings, and a release process that keeps symbols without shipping them.
    First step
    Make sure the binary is exactly the build that crashed, then find the debug information of that same build. A stripped binary gives GDB addresses only. With the separate debug file produced from the same build, the same core shows function names, lines and many values, because the debug information describes those exact addresses.
    Follow-ups

    From the lesson Debugging C++ with LLDB and GDB

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  15. Mid to senior

    Your team wants to ship a C++ service with standard library hardening, but the latency budget allows at most 3 % more CPU. A benchmark shows libc++'s fast mode costing 12 % in one hot loop and nothing measurable elsewhere. What do you ship, how do you measure it, and what do you change?

    What it tests
    Choosing a hardening level from measurements, reading a micro-benchmark against whole-service cost, and removing checks locally without turning hardening off.
    First step
    Measure the whole service, not the loop: run the release and the hardened presets under the same load and compare CPU per request and p99 latency. A loop that costs 12 % but takes 5 % of the service's time adds about 0.6 % in total, well inside the budget.
    Follow-ups

    From the lesson Sanitizer and hardened C++ build presets

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  16. Mid to senior

    After an out-of-bounds crash in production, a teammate proposes shipping the AddressSanitizer build of the service from now on, "so that the next bug is caught". Evaluate the idea and propose what you would ship instead.

    What it tests
    The cost and design limits of sanitizers in production, the difference between finding bugs and hardening, and a realistic plan of builds for tests and for production.
    First step
    Put numbers on the cost first: Clang's documentation gives about 2× the time for ASan, with more memory as well. Then separate the two goals: finding bugs before release, and stopping them safely after release.
    Follow-ups

    From the lesson Sanitizer and hardened C++ build presets

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  17. Fresher to mid

    After the team moves to GCC 15, a debug build that worked for years aborts in a test with "Assertion '__n < this->size()' failed" inside std::vector. The release build still passes. Is the new compiler wrong, and what do you do?

    What it tests
    Reading a standard library assertion as a bug report, telling a new check from a new bug, and fixing the caller instead of silencing the check.
    First step
    Read the assertion as a bug report: operator[] was called with an index that is not less than size(). Then ask what changed with the compiler: a check that did not run before can expose a bug that was always there, and the release build passes only because nothing checks there.
    Follow-ups

    From the lesson Sanitizer and hardened C++ build presets

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  18. Senior to staff

    Your team turns on clang-tidy with every check and gets 2,300 findings on a 60,000-line code base. How do you roll it out without stopping work, and how do you decide which checks stay?

    What it tests
    Staging checks, separating bug-finding checks from taste, baselines and changed-files runs, automatic fixes, NOLINT discipline and making the chosen checks fail CI.
    First step
    Group the 2,300 findings by check name before deciding anything, and look at what each of the largest groups asks for. Then ask which checks would have caught bugs this team has actually shipped: those are the candidates for the first stage.
    Follow-ups

    From the lesson clang-tidy, clang-format and static analysis

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  19. Mid to senior

    The clang-format check in CI keeps failing on files that developers formatted locally, and each fix produces new differences elsewhere. What is going on, and how do you set it up so that it never happens again?

    What it tests
    Making a formatter give the same result on every machine: versions, style files, editors, CI checks and formatting only the lines a change touches.
    First step
    Compare clang-format --version on a developer's machine, in the editor and in CI. Then format one failing file with each of them, using the same style file, and compare the outputs line by line before changing any setting.
    Follow-ups

    From the lesson clang-tidy, clang-format and static analysis

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  20. Mid to senior

    A colleague says a module is safe because clang-tidy and the static analyzer report nothing on it. What can those tools miss, and what would you add before trusting the module?

    What it tests
    Knowing the limits of static tools, telling an empty report from a well-covered module, and choosing the run-time tools and tests that cover the rest.
    First step
    Ask what the tools were able to see before trusting what they did not report: which checks ran, on which files, with which flags. A cheap test is to plant a known bug in the module and see whether each tool reports it.
    Follow-ups

    From the lesson clang-tidy, clang-format and static analysis

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  21. Fresher to mid

    You made a parsing function three times faster in a micro-benchmark, but the whole program became only 4 % faster. Explain the numbers, and describe how you should have chosen what to optimise.

    What it tests
    Amdahl's law with real numbers, the difference between a function's speed and its share of the run time, and a profile-first method.
    First step
    Work out the share. If a part takes a fraction p of the run time and becomes s times faster, the program takes 1 − p + p / s of its old time. With s = 3 the saving is 2p / 3, and a saving of 0.04 gives p = 0.06: the function was only 6 % of the run time.
    Follow-ups

    From the lesson Profiling C++: finding where the time goes

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  22. Mid to senior

    After a release, a C++ service's p99 latency doubled, yet a CPU profile under the same load looks the same as before and CPU use did not rise. Why can a CPU profile miss the cause, and what do you measure instead?

    What it tests
    The difference between on-CPU and off-CPU time, what sampling profilers record, and tools for waiting time: locks, I/O and scheduling.
    First step
    A CPU profile only sees threads while they run. If requests got slower without more CPU work, they spend the extra time waiting: on a lock, on I/O, on another service or in a queue. Compare wall-clock time per request with CPU time per request; the gap is the waiting time to explain.
    Follow-ups

    From the lesson Profiling C++: finding where the time goes

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  23. Mid to senior

    The top line of a perf report is memcpy, with 35 % self time, in a C++ program that never calls memcpy directly. What does that tell you, and how do you find the code to change?

    What it tests
    Reading self against total time, using callers in a call-graph report or flame graph, and the C++ habits that produce hidden copies.
    First step
    memcpy is where the bytes are copied, not why. Ask for its callers: perf report with call graphs (or a flame graph) shows which of your functions sit below memcpy in the stacks. Hidden copies usually come from objects passed or returned by value, strings built repeatedly, or vectors that grow without reserve.
    Follow-ups

    From the lesson Profiling C++: finding where the time goes

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  24. Fresher to mid

    Your contest template uses <bits/stdc++.h>, __int128 to compute (a * b) % m for m up to 10^18, and long for 64-bit counts. You must now build it with MSVC on Windows and test it on a Mac. What breaks, and how do you port it without losing correctness?

    What it tests
    Recognising library headers, compiler extensions and data-model assumptions, and replacing each with a portable construct that keeps the arithmetic exact.
    First step
    List the assumptions, then test each on each target. The header exists only in libstdc++; __int128 exists only in GCC and Clang on 64-bit targets; long has 4 bytes on Windows. MSVC fails on the header first and on __int128 next, and Apple clang stops at the header too, so build on both before fixing anything.
    Follow-ups

    From the lesson Portability across compilers, platforms and judges

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  25. Mid to senior

    A string hash function gives different values on an Arm64 Linux server than on x86 laptops and Macs, so cache keys stop matching. The code compiles without warnings on every machine. What is a likely cause, how do you prove it, and how do you fix it?

    What it tests
    The implementation-defined sign of plain char, how it changes arithmetic on bytes above 0x7F, reproducing a platform difference locally, and writing byte code that is the same everywhere.
    First step
    Look for arithmetic on plain char: hash functions often add or shift each char into the result. Plain char is signed on x86 and on Apple's arm64 platforms but unsigned on Arm64 Linux, so a byte such as 0xC3 of a UTF-8 text is -61 on one machine and 195 on the other. Hashes of pure ASCII text match; the others differ.
    Follow-ups

    From the lesson Portability across compilers, platforms and judges

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  26. Mid to senior

    Your open-source C++ library promises to support GCC, Clang and MSVC on Linux, macOS and Windows, but each pull request may use about 30 minutes of CI time. Design the matrix: which jobs, with which flags, and what each one is there to catch.

    What it tests
    Choosing a small set of compiler and platform jobs that covers headers, extensions, data models, char signedness and library gaps, and spending the budget where failures are most likely.
    First step
    Start from what can differ, not from every combination: nine compiler and system pairs are too many for 30 minutes. List the standard libraries and data models the library promises, give each one a job that would fail on it, and only then add cheap variants for what those jobs cannot see.
    Follow-ups

    From the lesson Portability across compilers, platforms and judges

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All C++ interview questions · The C++ track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.