For novices, coding in C/C++ often has two major challenges that coding in other programming languages does not:
Memory

C's memory model is not explicitly enforced by its runtime system, and novices often write code that violates the memory model and causes cryptic segmentation faults/memory corruptions. This is one major source of frustration.

cee.studio Solution
Instant and informative feedback on the occurence of mishandled pointers and memory Learn more:
Pointer

Understanding pointer requires the practice of mentally visualizing how memory locations are linked through pointers by looking at C code. Not mastering pointer escalates the first challenge and causes more frustration.

cee.studio Solution
Instant visual feedback as to how each statement manipulates pointers and memory Learn more

The Guard Rail of C's Memory Model

cee.studio backend explicitly enforces C's memory model and reports many memory access violations with determinstic and informative diagnostic messages. This feature removes the major sources of frustration in C/C++. The diagnostic messages are crafted to convey C's memory model with information to make a fix.

Comparision with other memory error finding tools in table
Examples

The following are examples of common memory access violations. The companying live demos can be executed by clicking .

Writing to the outside of a memory space Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main (int argc, char ** argv)
{
  char p[10];
  p[100] = 0; // write to the outside of p
  return 0;
}

    

This memory access violation is reported as

Memory access error: writing to the outside of a memory space; abort execution.
# Writing 1 bytes to 0xffd77320 will clobber other memory-blocks.
#
# The memory-block-to-be-written (start:0xffd772bc, size:10 bytes) is bound to 'p' at
#     file:/prog.c::6, 8
#
#  0xffd772bc               0xffd772c5
#  +------------------------------+
#  |the memory-block-to-be-written|......
#  +------------------------------+
#                                     ^~~~~~~~~~
#           the write starts at 0xffd77320 that is 90 bytes after the memory-block end.
#
# Stack trace (most recent call first) of the write.
# [0]  file:/prog.c::7, 3
# [1]  [libc-start-main]

            
Dereferencing a non-pointer Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main (int argc, char ** argv)
{
  char *p = 10;
  printf("%c\n", p[1]);
  return 0;
}

        

This memory access violation is reported as

Memory access error: dereferencing a non-pointer; abort execution.
# Reading 1 bytes from an illegit address (0xb).
#
# Stack trace (most recent call first) of the read.
# [0]  file:/prog.c::8, 3
# [1]  [libc-start-main]

    
Dereferencing an uninitialized pointer Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main (int argc, char ** argv)
{
  char *p;
  printf("%c\n", p[1]);
  return 0;// exit code
}

                

This memory access violation is reported as

Memory access error: dereferencing an uninitialized pointer; abort execution.
# Reading 1 bytes from a random address (0xffae9c70).
#
# Stack trace (most recent call first) of the read.
# [0]  file:/prog.c::7, 3
# [1]  [libc-start-main]
Freeing a null pointer Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int * p = 0;
int main (int argc, char ** argv)
{
  free(p);
  return 0;
}

        

This memory access violation is reported as

Memory access error: freeing a non-pointer; abort execution.
# free 0x0, which does not point to a legit memory space.
# Stack trace (most recent call first) of the error.
# [0]  file:/musl-1.1.10/src/malloc/safe_malloc.c::93, 5
# [1]  file:/prog.c::8, 3
# [2]  [libc-start-main]

Freeing a freed memory space Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main (int argc, char ** argv)
{
  char * p = malloc(10);
  free(p);
  free(p);
  return 0;// exit code
}

        

This memory access violation is reported as

Memory access error: freeing a freed memory space; abort execution.
# The memory-block-to-be-freed (start:0x8dda010, size:10 bytes) is allocated at
#     file:/prog.c::7, 14
#
# Stack trace (most recent call first) of the error.
# [0]  file:/musl-1.1.10/src/malloc/new_dts_memory_util.c::37, 5
# [1]  file:/musl-1.1.10/src/malloc/safe_malloc.c::110, 3
# [2]  file:/prog.c::9, 3
# [3]  [libc-start-main]

        
Freeing an invalid pointer Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main (int argc, char ** argv)
{
  int * p = (int *)malloc(sizeof(int)*10);
  p++;
  free(p);
  return 0;// exit code
}

This memory access violation is reported as

Memory access error: freeing at non-memory start; abort execution.
# free 0x9209014, which does not point to the start of a memory space.
# Stack trace (most recent call first) of the error.
# [0]  file:/musl-1.1.10/src/malloc/safe_malloc.c::99, 5
# [1]  file:/prog.c::9, 3
# [2]  [libc-start-main]
Clobbering immutable string Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main (int argc, char ** argv)
{
  char * p = "hello world";
  p[0] = 0;
  return 0;
}

        

This memory access violation is reported as

Memory access error: clobbering immutable data; abort execution.
# Writing 1 bytes to 0x8135a64 will clobber immutable data.
#
# The memory-block-to-be-written ('hello world', size:12 bytes) is allocated at
#     file:/prog.c
# The memory-block-to-be-written contains immutable data.
#
# Stack trace (most recent call first) of the write.
# [0]  file:/prog.c::8, 3
# [1]  [libc-start-main]
Using a freed memory space Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main (int argc, char ** argv)
{
  char * p = malloc(10);
  free(p);
  *p = 10;
  return 0;
}

This memory access violation is reported as

Memory access error: writing to a freed memory space; abort execution.
# Writing 1 bytes to 0x9678010 can cause data corruption.
#
# The memory-block-to-be-written (start:0x9678010, size:10 bytes) was allocated at
#     file:/prog.c::6, 14
# It was freed, and its allocation location might be distorted by subsequent reuses.
#
#
# Stack trace (most recent call first) of the write.
# [0]  file:/prog.c::8, 3
# [1]  [libc-start-main]
Reading uninitialized memory Live demo
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main (int argc, char ** argv)
{
  char p[10];
  printf("%c\n", p[1]);
  return 0;
}

        

This memory access violation is reported as

Memory access warning: reading uninitialized memory; continue execution.
# Reading 1 bytes from 0xffe7a61d will read undefined data.
#
# The memory-block-to-be-read (start:0xffe7a61c, size:10 bytes) is bound to 'p' at
#     file:/prog.c::6, 8
# It is not initialized.
#
#  0xffe7a61c               0xffe7a625
#  +------------------------------+
#  | the memory-block-to-be-read  |
#  +------------------------------+
#                  ^~~~~~~~~~
#      the read starts at 1 bytes offset of the memory-block.
#
# Stack trace (most recent call first) of the read.
# [0]  file:/prog.c::7, 3
# [1]  [libc-start-main]
Exhausting call stack (a.k.a stack overflow) Live demo
int find(int p[], int ino) {
  if (p[ino] != ino) {
    find(p, ino);
  }
  return p[ino];
}
                

This memory access violation is reported as

Memory access error: exhausting the call stack (stack overflow); abort execution.
#
# Stack trace (most recent call first) of the overflow
# [0]  file:/prog.cc::10, 5
# [1]  file:/prog.cc::10, 5
# [2]  file:/prog.cc::10, 5
# [3]  file:/prog.cc::10, 5
# [4]  file:/prog.cc::10, 5
# [5]  file:/prog.cc::10, 5
# [6]  file:/prog.cc::10, 5
# [7]  file:/prog.cc::10, 5
# [8]  file:/prog.cc::10, 5
# [9]  file:/prog.cc::10, 5
# [10]  file:/prog.cc::10, 5
# [11]  file:/prog.cc::10, 5
# [12]  file:/prog.cc::10, 5
# [13]  file:/prog.cc::10, 5
# [14]  file:/prog.cc::10, 5
# [15]  file:/prog.cc::10, 5
# [16]  file:/prog.cc::10, 5
# ...

        

Turn Abstract Pointers to Concrete Points-to Graph

This feature does not work well with C++ code due to C++'s pervasive use of copy constructors.

cee.studio can record the execution of C code statement by statement. In the recorded execution, each frame consists of

The recorded execution can be rewound to any statements and replayed, providing a visualization of how memory locations are linked by pointers statement-by-statement. In each points-to graph, nodes represent the memory spaces, directed edges represent the points-to relations. Clicking a node will highlight the statement that allocates a memory space. Clicking an edge will highlight the assignment statement that created that points-to relation.

Example

The following GIF shows a recorded execution of creating a sorted singly linked list.

The following accompanying live demo can be executed by clicking .

Generic sorted single linked list Live demo