For novices, coding in C/C++ often has two more challenges than coding in other languages:
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 occurrence of mishandled pointers and memory Learn more:
Pointer

Understanding pointer requires the practice of visualizing how different 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-SDK explicitly enforces C's memory model and reports many memory access violations with deterministic 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 block 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 block; abort!
# 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!
# 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!
# 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!
# free 0x0, which does not point to a legit memory block.
# 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 block 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 block; abort!
# The memory-block-to-be-freed (start:0x9494010, size:10 bytes) was allocated at
#    file:/prog.c::14, 14
#    [libc-start-main]
# It has been freed at
#    file:/prog.c::10, 5
#    file:/prog.c::15, 3
#    [libc-start-main]
#
# Stack trace (most recent call first) of the error.
# [0]  file:/musl-1.1.10/src/malloc/new_dts_memory_util.c::40, 5
# [1]  file:/musl-1.1.10/src/malloc/safe_malloc.c::114, 3
# [2]  file:/prog.c::16, 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!
# free 0x9209014, which does not point to the start of a memory block.
# 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!
# 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 block 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 block; abort!
# Writing 1 bytes to 0x929e010 may clobber other memory blocks.
#
# The memory-block-to-be-written (start:0x929e010, size:10 bytes) was allocated at
#    file:/prog.c::10, 14
#    [libc-start-main]
# It has been freed at
#    file:/prog.c::11, 3
#    [libc-start-main]
# The allocation/free locations could have been distorted by subsequent reuses.
#
#
# Stack trace (most recent call first) of the write.
# [0]  file:/prog.c::12, 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!
#
# 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 blocks, directed edges represent the points-to relations. Clicking on a node will highlight the statement that allocates a memory block.

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