Concepts / Memory Management When Converting from malloc and free to new and delete

Memory Management When Converting from malloc and free to new and delete

When a C program is converted to C++, or when C and C++ code have to work together in one program, the two languages meet at the linker.

  • Programming

Why Linkage Matters at the C and C++ Boundary

When a C program is converted to C++, or when C and C++ code have to work together in one program, the two languages meet at the linker. The linker is the tool that connects a call made in one compiled piece of code to the function that is defined in another piece. Whether that connection works smoothly depends on the linkage conventions each language uses, and the two languages do not always use the same ones. This article explains why that is so and how the extern "C" declaration bridges the gap.

What Linkage Means

Definition

Linkage describes how functions and variables are accessed across different source files and libraries. When a program is built from several pieces, each call in one piece has to be connected to the function defined in another piece.

Think of a program built from two files. One file calls a function named sqrt, and a different file, or a library, contains the definition of sqrt. Nothing in the calling file contains the body of that function. The linker's job is to match the call with the definition. Linkage is the set of rules that makes that matching possible, so a call in one piece can find the right function in another.

Why C and C++ Link Differently

C and C++ can be implemented to use different linkage conventions, and in practice they often are. The most basic reason is that C++ places a greater emphasis on type checking. A second, practical reason is that C++ supports overloading.

Overloading lets a program contain two global functions with the same name. The source's example is two functions that are both called open(). C does not allow this. Because C++ allows it, the linker has to be able to tell the two functions apart in a way that reflects the rules of the language. Since C has no such need, C linkage can treat a name more simply. This difference is why linkage needs special attention whenever C and C++ code are mixed.

Reading an extern C Declaration

To call a C function from a C++ program fragment, you declare it with extern "C". The same declaration form also gives a C++ function C linkage, so that the function can be called from a C program fragment. The source's standard example is the declaration of the square-root function, which takes a double and returns a double.

cpp
Notes on the code
  • extern "C" is the linkage specification: it asks for C linkage for this declaration
  • double (first) is the return type
  • sqrt is the function name
  • (double) is the parameter list, which takes one double argument
  • The trailing semicolon ends the declaration
externlinkage specificationkeyword"C"requests C linkagedoublereturn typesqrtfunction name(double)parameter list;ends the declaration
Which part of the declaration tells the compiler to use C linkage, and what does each remaining part mean?

Reading the declaration from left to right: extern "C" is the part that changes the linkage. The double before the name is the return type, sqrt is the name, and the parentheses hold the parameter list. Everything after extern "C" is an ordinary function declaration. The linkage specification is added to the declaration; it does not replace the function's type information.

How Overloading Changes the Picture

The difference between the two languages is easiest to see by comparing the same function name under each set of rules. Under C rules, one name refers to one global function in a scope, so the name alone is enough for the linker to find it. Under C++ rules, several overloads can share the name open, and the linker must distinguish them. The diagram below shows the two situations side by side. The exact internal naming scheme a C++ compiler uses is not described in the available material, so the diagram shows only the distinction itself.

openonly one global open inscopeopen(int)overload with an intparameteropen(const char*)overload with a stringparameter
Why does a C++ overloaded function need more than its plain name to be linked, while a C function does not?

What a Linkage Specification Changes

A linkage specification changes how a function is linked. It does not change how the function is checked. This is the most important point to remember. A function declared with extern "C" still follows the C++ rules for function calls and argument checking, and it still takes part in overload resolution at the call site.

AspectAffected by extern "C"?What it means
How the function is linkedYesThe declaration gives the function C linkage, so C and C++ code can connect to it
Argument type checkingNoC++ checking rules still apply to every call
Overload resolution at the call siteNoC++ still chooses among overloads by the C++ rules
Calling it from a C++ fragmentEnabledThe declaration lets C++ code call a C function
Calling it from a C fragmentEnabledThe same form lets a C++ function be called from C code

What a linkage specification alters and what it leaves alone

C source filedefines the C functionC compilercompiled C fragmentlinkermatches each call to itsdefinitionlinked programC++ source filecalls it with extern "C"C++ compilercompiled C++ fragmentits call is linked to Ccompiled bycompiled byproducesproducesinput toinput toproduces
How do the C compiler, the C++ compiler, and the linker cooperate so that a C++ call resolves to a C function?

The pipeline shows the division of labor. Each compiler handles its own language, and the linker's task is to join the compiled pieces. The declaration with extern "C" in the C++ file is what tells that side of the program which linkage convention to expect for the C function, so the call and the definition can meet at the linker.

Does the Declaration Relax the Checks?

What do you think happens?

A function is declared with extern "C", and then it is called with arguments of the wrong type. Does the extern "C" declaration relax the C++ type checks for that call?

  • Yes, C linkage turns off argument checking

  • No, the linkage specification affects linkage only and C++ checking still applies

Reveal answer
Answer:

No. The linkage specification affects linkage only. The C++ rules for function calls and argument checking still apply.

Extern "C" changes the linkage convention, which is how the function is connected by the linker. It does not change how the function's arguments are checked when the function is called.

Worked Example: Calling sqrt from Both Languages

Worked example

Declaring sqrt so both C and C++ can use it

The square-root function takes and returns a double. How can it be called from a C++ fragment and also be made available to a C fragment?

  1. 1
    Declare the function with extern "C"

    The declaration extern "C" double sqrt(double); gives the function C linkage. This is the form the source uses for the standard square-root example.

  2. 2
    Call it from a C++ fragment

    With the declaration in place, sqrt(double) can be called from a C++ code fragment. The declaration tells the C++ side which linkage convention the function follows.

  3. 3
    Call it from a C fragment

    The same declaration allows sqrt(double) to be called from a C code fragment, because the function has C linkage.

  4. 4
    Compile the definition either way

    The definition of sqrt(double) can be compiled either as a C function or as a C++ function. The declaration is the point where the two languages agree on how the function is linked.

Result

The extern "C" declaration is the agreement point: one function with C linkage can be called from both a C and a C++ fragment, and the declaration does not change the argument checking the function receives.

Common Mistakes at the C and C++ Boundary

  • Common mistake

    Assuming extern "C" turns off type checking

    What it looks like

    A function declared with extern "C" is called with an argument of the wrong type, and the programmer expects the compiler to accept it.

    Why it fails

    A linkage specification affects linkage only. The C++ rules for function calls and argument checking still apply.

    Do this instead

    Keep the call's arguments matching the declared parameter types. The extern "C" declaration only controls how the function is linked.

  • Common mistake

    Expecting a link error to appear only at the call site

    What it looks like

    A C header is included in C++ code without extern "C", and the program fails to link even though the code looks correct.

    Why it fails

    Without the linkage specification, the C++ side expects C++ linkage for the function, so the linker may not find a matching C definition.

    Do this instead

    Wrap the C declarations in an extern "C" block where the C++ code includes them, so the function is declared with C linkage.

  • Common mistake

    Declaring two C-linkage functions with the same name in one scope

    What it looks like

    Two overloads of open are both given C linkage in the same scope.

    Why it fails

    C does not allow overloading, and only one function of a given name in a scope can have C linkage.

    Do this instead

    Give the C-linkage function a single name in that scope, and use distinct names for functions that need separate definitions.

  • Common mistake

    Treating linkage as a fix for all conversion problems when it only addresses how functions are connected

Edge Case: One C-Linkage Name per Scope

Edge case

Only one function of a given name in a scope can have C linkage, because C does not allow overloading. This means that even in C++, a name that is meant to be called from C cannot be overloaded with several C-linkage versions in the same scope. The restriction follows from the C rule being applied to that name, not from any change in how the call is checked.

Practice: Placing the Wrapper

EASY

A C library header declares int add(int a, int b); and a C++ file includes that header directly. Where should the extern "C" wrapper go, and which part of the code does it change?

Hints
  • Ask which side of the boundary needs to know that add has C linkage.
  • Remember that the wrapper changes linkage, not the parameter types or how the call is checked.
  • The wrapper belongs around the declaration that the C++ code sees when it includes the C header.

Summary of Linkage at the Boundary

  1. 1
    C and C++ can use different linkage conventions, mainly because C++ emphasizes type checking and supports overloading.
  2. 2
    A declaration with extern "C" gives a function C linkage, so C++ code can call a C function and C code can call a C++ function declared the same way.
  3. 3
    A linkage specification changes how a function is linked, but not how it is checked, so C++ argument checking and overload resolution still apply.
  4. 4
    Only one function of a given name in a scope can have C linkage, because C does not allow overloading.
  5. 5
    Missing or misplaced extern "C" can cause link errors when C code is included in C++.

At a glance

  • C and C++ can use different linkage conventions, mainly because C++ emphasizes type checking and supports overloading.
  • extern "C" declares a function with C linkage so that C and C++ fragments can call it.
  • A linkage specification changes linkage only; C++ type checking and overload resolution still apply.
  • Only one function of a given name in a scope can have C linkage, since C does not allow overloading.
  • Missing or misplaced extern "C" declarations are a common cause of link errors when C code is used in C++.

Related concepts

More concepts starting with M