diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
index 24963982abf4105729497815964daef086a88026..bb394a59ac9f8316287f85d421c77bb1d2fc451e 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
@@ -151,7 +151,9 @@ static void memory_init(int *argc_ref, char *** argv_ref, size_t ptr_size) {
   increase_stack_limit(get_stack_size()*2);
   /* Allocate and log shadow memory layout of the execution. */
   init_memory_layout(argc_ref, argv_ref);
+  /* Make sure the layout holds and output it (only in debug mode) */
   DEBUG_PRINT_LAYOUT;
+  DVALIDATE_SHADOW_LAYOUT;
   /* Track program arguments. */
   if (argc_ref && argv_ref)
     argv_alloca(*argc_ref, *argv_ref);
diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
index e1fb8c7bebb93ba1f091d6050ae82ec7b639ff20..10b20224d31c199aa419d93f513ce1c17940954b 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
@@ -194,37 +194,61 @@ const uint64_t static_readonly_masks [] = {
 };
 /* }}} */
 
-/* E-ACSL predicates {{{ */
-/* See definitions for documentation */
-static uintptr_t heap_info(uintptr_t addr, char type);
-static uintptr_t static_info(uintptr_t addr, char type, int global);
-static int heap_allocated(uintptr_t addr, size_t size);
-static int static_allocated(uintptr_t addr, long size, int global);
-static int freeable(void *ptr);
-
-/*! \brief Wrapper around ::static_allocated for stack addresses. */
-#define stack_allocated(_addr, _size)  static_allocated(_addr, _size, 0)
-/*! \brief Wrapper around ::static_allocated for global addresses. */
-#define global_allocated(_addr, _size) static_allocated(_addr, _size, 1)
-
-/*! \brief Quick test to check if a static location belongs to allocation.
- * This macro really belongs where static_allocated is defined, but
- * since it is used across this whole file it needs to be defined here. */
-#define static_allocated_one(addr, global) \
-  ((int)PRIMARY_SHADOW(addr, global))
-
-/* Runtime assertions */
-#define VALIDATE_ALIGNMENT(_addr) \
-  vassert(((uintptr_t)_addr) % HEAP_SEGMENT == 0,  \
+/* Runtime assertions (debug mode) {{{ */
+#ifdef E_ACSL_DEBUG
+#define DVALIDATE_ALIGNMENT(_addr) \
+  DVASSERT(((uintptr_t)_addr) % HEAP_SEGMENT == 0,  \
       "Heap base address %a is unaligned", _addr)
 
-/* Debug-level macros for validating memory accesses and allocation */
-#ifdef E_ACSL_DEBUG
-#  define DVALIDATE_SHADOW_LAYOUT \
-    DVASSERT(mem_layout.initialized != 0, "Un-initialized shadow layout", NULL)
+/* Debug function making sure that the order of program segments is as expected
+ * and that the program and the shadow segments used do not overlap. */
+static void validate_memory_layout() {
+  /* Check that the struct holding memory layout is marked as initialized. */
+  DVASSERT(mem_layout.initialized != 0, "Un-initialized shadow layout", NULL);
+  /* Make sure the order of program segments is as expected, i.e.,
+   * top to bittom: stack -> tls -> heap -> global*/
+
+  #define NO_MEM_SEGMENTS 11
+  uintptr_t segments[NO_MEM_SEGMENTS][2] = {
+     {mem_layout.stack.start, mem_layout.stack.end},
+     {mem_layout.stack.prim_start, mem_layout.stack.prim_end},
+     {mem_layout.stack.sec_start, mem_layout.stack.sec_end},
+     {mem_layout.tls.start, mem_layout.tls.end},
+     {mem_layout.tls.prim_start, mem_layout.tls.prim_end},
+     {mem_layout.tls.sec_start, mem_layout.tls.sec_end},
+     {mem_layout.global.start, mem_layout.global.end},
+     {mem_layout.global.prim_start, mem_layout.global.prim_end},
+     {mem_layout.global.sec_start, mem_layout.global.sec_end},
+     {mem_layout.heap.start, mem_layout.heap.end},
+     {mem_layout.heap.prim_start, mem_layout.heap.prim_end}
+  };
+
+  /* Make sure all segments (shadow or otherwise) are disjoint */
+  size_t i, j;
+  for (int i = 0; i < NO_MEM_SEGMENTS; i++) {
+    uintptr_t *src = segments[i];
+    DVASSERT(src[0] < src[1],
+      "Segment start is greater than segment end %lu < %lu\n", src[0], src[1]);
+    for (int j = 0; j < NO_MEM_SEGMENTS; j++) {
+      if (i != j) {
+        uintptr_t *dest = segments[j];
+        DVASSERT(src[1] < dest[0] || src[0] > dest[1],
+          "Segment [%lu, %lu] overlaps with segment [%lu, %lu]",
+          src[0], src[1], dest[0], dest[1]);
+      }
+    }
+  }
 
+  DVASSERT(mem_layout.stack.end > mem_layout.tls.end,
+      "Unexpected location of stack (above tls)", NULL);
+  DVASSERT(mem_layout.tls.end > mem_layout.heap.end,
+      "Unexpected location of tls (above heap)", NULL);
+  DVASSERT(mem_layout.heap.end > mem_layout.global.end,
+      "Unexpected location of heap (above global)", NULL);
+}
+
+#  define DVALIDATE_SHADOW_LAYOUT validate_memory_layout()
 #  define DVALIDATE_HEAP_ACCESS(_addr, _size) \
-     DVALIDATE_SHADOW_LAYOUT; \
      DVASSERT(IS_ON_HEAP(_addr), \
        "Expected heap location: %a\n   ", _addr); \
      DVASSERT(heap_allocated((uintptr_t)_addr, _size), \
@@ -232,7 +256,6 @@ static int freeable(void *ptr);
 
 #  define segstr(_global)  ((_global) ? "global" : "stack")
 #  define DVALIDATE_STATIC_ACCESS(_addr, _size, _global) \
-     DVALIDATE_SHADOW_LAYOUT; \
      DVASSERT(IS_ON_STATIC(_addr, _global), \
        "Expected %s location: %a\n   ", segstr(_global), _addr); \
      DVASSERT(static_allocated((uintptr_t)_addr, _size, _global), \
@@ -240,7 +263,6 @@ static int freeable(void *ptr);
         segstr(_global),  _addr, _size)
 
 #  define DVALIDATE_STATIC_LOCATION(_addr, _global) \
-     DVALIDATE_SHADOW_LAYOUT; \
      DVASSERT(IS_ON_STATIC(_addr, _global), \
        "Expected %s location: %a\n   ", segstr(_global), _addr); \
      DVASSERT(static_allocated_one((uintptr_t)_addr, _global), \
@@ -251,8 +273,29 @@ static int freeable(void *ptr);
 #  define DVALIDATE_HEAP_ACCESS
 #  define DVALIDATE_STATIC_ACCESS
 #  define DVALIDATE_STATIC_LOCATION
+#  define DVALIDATE_ALIGNMENT
 /*! \endcond */
 #endif
+/* }}} */
+
+/* E-ACSL predicates {{{ */
+/* See definitions for documentation */
+static uintptr_t heap_info(uintptr_t addr, char type);
+static uintptr_t static_info(uintptr_t addr, char type, int global);
+static int heap_allocated(uintptr_t addr, size_t size);
+static int static_allocated(uintptr_t addr, long size, int global);
+static int freeable(void *ptr);
+
+/*! \brief Wrapper around ::static_allocated for stack addresses. */
+#define stack_allocated(_addr, _size)  static_allocated(_addr, _size, 0)
+/*! \brief Wrapper around ::static_allocated for global addresses. */
+#define global_allocated(_addr, _size) static_allocated(_addr, _size, 1)
+
+/*! \brief Quick test to check if a static location belongs to allocation.
+ * This macro really belongs where static_allocated is defined, but
+ * since it is used across this whole file it needs to be defined here. */
+#define static_allocated_one(addr, global) \
+  ((int)PRIMARY_SHADOW(addr, global))
 
 /*! \brief Shortcut for executing statements based on the segment a given
  * address belongs to.
@@ -334,8 +377,6 @@ static const char short_offsets_base [] = { 0, 1, 2, 4, 7, 11, 16, 22, 29 };
  * \param global - if evaluates to a non-zero value then global region is used,
  * otherwise program stack is used. */
 static void shadow_alloca(void *ptr, size_t size, int global) {
-  DVALIDATE_SHADOW_LAYOUT;
-
   unsigned char *prim_shadow =
     (unsigned char*)PRIMARY_SHADOW(ptr, global);
   uint64_t *prim_shadow_alt =
@@ -408,7 +449,6 @@ static void static_shadow_freea(void *ptr, int global) {
  * global memory block and 0 otherwise. Note, this function is only safe if
  * applied to a stack or global address. */
 static int static_allocated(uintptr_t addr, long size, int global) {
-  DVALIDATE_SHADOW_LAYOUT;
   unsigned char *prim_shadow = (unsigned char*)PRIMARY_SHADOW(addr, global);
   /* Unless the address belongs to tracked allocation 0 is returned */
   if (prim_shadow[0]) {
@@ -594,7 +634,6 @@ static void initialize_static_region(uintptr_t addr, long size, int global) {
 static void mark_readonly (uintptr_t addr, long size) {
   /* Since read-only blocks can only be stored in the globals  segments (e.g.,
    * TEXT), this function required ptr carry a global address. */
-  DVALIDATE_SHADOW_LAYOUT;
   DASSERT(IS_ON_GLOBAL(addr));
   DASSERT(global_allocated(addr, 1));
   DVASSERT(!(addr - base_addr(addr) + size > block_length(addr)),
@@ -643,7 +682,7 @@ static void set_heap_segment(void *ptr, size_t size, size_t init) {
   if (!ptr)
     return;
 
-  VALIDATE_ALIGNMENT(ptr); /* Make sure alignment is right */
+  DVALIDATE_ALIGNMENT(ptr); /* Make sure alignment is right */
   heap_allocation_size += size; /* Adjuct tracked allocation size */
 
   /* Get aligned size of the block, i.e., an actual size of the
@@ -736,7 +775,6 @@ static void* shadow_calloc(size_t nmemb, size_t size) {
 /* Heap deallocation (free) {{{ */
 static void shadow_free(void *res) {
   char *ptr = (char *)res;
-  DVALIDATE_SHADOW_LAYOUT;
   if (ptr != NULL) { /* NULL is a valid behaviour */
     if (freeable(ptr)) {
       size_t size = block_length(ptr);
@@ -754,7 +792,6 @@ static void shadow_free(void *res) {
 
 /* Heap reallocation (realloc) {{{ */
 static void* shadow_realloc(void *p, size_t size) {
-  DVALIDATE_SHADOW_LAYOUT;
   char *ptr = (char*)p;
   char *res = NULL; /* Resulting pointer */
   /* If the pointer is NULL then realloc is equivalent to malloc(size) */
@@ -768,7 +805,7 @@ static void* shadow_realloc(void *p, size_t size) {
     if (freeable(ptr)) { /* ... and valid for free  */
       size_t alloc_size = ALLOC_SIZE(size);
       res = native_realloc(ptr - HEAP_SEGMENT, alloc_size);
-      VALIDATE_ALIGNMENT(res);
+      DVALIDATE_ALIGNMENT(res);
 
       /* realloc succeeds, otherwise nothing needs to be done */
       if (res != NULL) {
@@ -892,7 +929,6 @@ static int shadow_posix_memalign(void **memptr, size_t alignment, size_t size) {
  * block and a 0 otherwise. Note, this function is only safe if applied to a
  * heap address. */
 static int heap_allocated(uintptr_t addr, size_t size) {
-  DVALIDATE_SHADOW_LAYOUT;
   /* Offset within the segment */
   size_t block_offset = addr%HEAP_SEGMENT;
   /* Address of the shadow segment the address belongs to */
@@ -925,7 +961,6 @@ static int heap_allocated(uintptr_t addr, size_t size) {
  * implementation is preferred for performance reasons. */
 static int freeable(void *ptr) {
   uintptr_t addr = (uintptr_t)ptr;
-  DVALIDATE_SHADOW_LAYOUT;
   if (!IS_ON_HEAP(addr))
     return 0;
   /* Offset within the segment */
@@ -942,7 +977,6 @@ static int freeable(void *ptr) {
  * memory. NB: If `addr` does not belong to a valid heap region this function
  * returns 0. */
 static int heap_initialized(uintptr_t addr, long len) {
-  DVALIDATE_SHADOW_LAYOUT;
   /* Unallocated heap address */
   if (!heap_allocated(addr, len))
     return 0;
@@ -1068,7 +1102,6 @@ static void initialize_heap_region(uintptr_t addr, long len) {
 /*! \brief Initialize a chunk of memory given by its start address (`addr`)
  * and byte length (`n`). */
 static void initialize(void *ptr, size_t n) {
-  DVALIDATE_SHADOW_LAYOUT;
   TRY_SEGMENT(
     (uintptr_t)ptr,
     initialize_heap_region((uintptr_t)ptr, n),
@@ -1078,7 +1111,7 @@ static void initialize(void *ptr, size_t n) {
 }
 /* }}} */
 
-/* Internal state print {{{ */
+/* Internal state print (debug mode) {{{ */
 #ifdef E_ACSL_DEBUG
 /* ! \brief Print human-readable representation of a byte in a primary
  * shadow */
diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h
index 796ada15b3f7fa7e0e14a2986569467942cfcc68..12b0b9f56f73db1eba5c18f42a3906e02d7340f4 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_shadow_layout.h
@@ -253,19 +253,19 @@ NOTE: With mmap allocations heap does not necessarily grows from program break
  * shadow spaces. */
 struct memory_segment {
   uintptr_t start; //!< Least address in application segment
-  uintptr_t end;   //!< Greatest address in application segment
+  uintptr_t end; //!< Greatest address in application segment
 
   size_t shadow_size; //!< Byte-size of shadow area
 
-  uintptr_t prim_start;  //!< Least address in primary shadow
-  uintptr_t prim_end;    //!< Greatest address in primary shadow
+  uintptr_t prim_start; //!< Least address in primary shadow
+  uintptr_t prim_end; //!< Greatest address in primary shadow
   uintptr_t prim_offset; //!< Primary shadow offset
 
-  uintptr_t sec_start;  //!< Least address secondary shadow
-  uintptr_t sec_end;    //!< Greatest address secondary shadow
+  uintptr_t sec_start; //!< Least address secondary shadow
+  uintptr_t sec_end; //!< Greatest address secondary shadow
   uintptr_t sec_offset; //!< Secondary shadow offset
 
-  int initialized;
+  int initialized; //! Notion on whether the layout is initialized
 };
 
 /*! \brief Full program memory layout. */
@@ -283,18 +283,18 @@ struct memory_layout {
 static void set_shadow_segment(struct memory_segment *seg, uintptr_t start,
     uintptr_t size, int secondary) {
   seg->start = start;
-  seg->end = seg->start + size;
+  seg->end = seg->start + size - 1;
   seg->shadow_size = size;
 
   void *prim_shadow = do_mmap(seg->shadow_size);
   seg->prim_start = (uintptr_t)prim_shadow;
-  seg->prim_end = seg->prim_start + seg->shadow_size;
+  seg->prim_end = seg->prim_start + seg->shadow_size - 1;
   seg->prim_offset = shadow_offset(prim_shadow, start);
 
   if (secondary) {
     void *sec_shadow = do_mmap(seg->shadow_size);
     seg->sec_start = (uintptr_t)sec_shadow;
-    seg->sec_end = seg->sec_start + seg->shadow_size;
+    seg->sec_end = seg->sec_start + seg->shadow_size - 1;
     seg->sec_offset = shadow_offset(sec_shadow, seg->start);
   } else {
     seg->sec_start = seg->sec_end = seg->sec_offset = 0;