Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

C++

C++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについて

投稿日:2022年2月26日 更新日:

 

<目次>

(1) C++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについて
 (1-1) 事象・発生状況
 (1-2) 原因
 (1-3) 対策
 (1-4) 参考

(1) C++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについて

本記事ではC++で発生した「 _CrtIsValidHeapPointer(block)」と「is_block_type_valid(header->_block_use)」エラーについてご紹介します。

(1-1) 事象・発生状況

C++のプログラムを実行した結果、以下のエラーが発生しました。

●エラーメッセージ

Debug Assertion Failed!

Program:
XXXX
Line XXX

Expression: _CrtIsValidHeapPointer(block)

(図111)

Debug Assertion Failed!

Program:
XXXX
Line XXX

Expression: is_block_type_valid(header->_block_use)

(図112)

●事象発生のサンプルプログラム

 
上記のエラーを再現するためのサンプルプログラムをご紹介します。
#include <iostream>
using namespace std;
int main(void) {

    int n1 = 10;
    int* n1p = &n1;
    delete[] n1p;

}

目次にもどる

(1-2) 原因

下記の原因が考えられます。

●メッセージ「_CrtIsValidHeapPointer」の原因

・解放されるべきポインタが既に有効でない(or正しくない)場合

(発生例)「new」していないのに「delete[]」している場合
    int n1 = 10;
    int* n1p = &n1;
    delete[] n1p;

●メッセージ「is_block_type_valid(header->_block_use)」の原因

・こちらもメモリの使用や解放に関連しているケースが多く、例えば同じアドレスブロックを繰り返し削除した場合などに発生する様です。

(発生例)「new」していないのに「delete」している場合
    int n1 = 10;
    int* n1p = &n1;
    delete n1p;

目次にもどる

(1-3) 対策

上記の発生例の場合、対策としては「delete」対応する「new」の定義を設ける事で解決する事ができます。

(例)
    int* n1p = new int;
    n1p[0] = 10;
    delete n1p;
(図131)

なので、チェックする観点の例としては以下の通りです。
①「delete」しているのに「new」されていない箇所が無いかを確認する
②「new」に対しては「delete」で解放になっているかを確認する
③「new 型[N]」に対しては「delete[]」で解放になっているか確認する

目次にもどる

(1-4) 参考

●参考1

ちなみに、上記の②と③のケースはエラーではなく、下図のような警告になるようです。単一の非配列オブジェクトの場合は「new」と「delete」で、逆に配列オブジェクトの場合は「new []」と「delete[]」を使います。

・②がNGの例
⇒「new」に対して「delete[]」で解放している
 
・③がNGの例
⇒「new []」に対して「delete」で解放している

●参考2:②と③のNGで起きている事

「new[]」で返却されるポインタは常に割当てされたメモリの先頭を見るとは限りません。なぜなら、動的にメモリを割り当てる際は、その「サイズ」の情報を「先頭」に保持するため、その分だけオフセット(補正)されてしまい、先頭はサイズの情報となるためです。
 
int* n1p = new int[10];

 

例えば、下記のポインタ定義では要素を10つ確保していますが、このポインタのサイズ(要素10個)の情報を保持するため、先頭は1要素目のデータではなく、サイズになります。なので、ここで通常「delete[]」とすべき所を「delete」としてしまうと、そのオフセット分がミスマッチとなり警告に繋がっているようです。
 
 

Adsense審査用広告コード


Adsense審査用広告コード


-C++

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

C++のポインタとは?概念や基本的な使い方をご紹介

  <目次> (1) C++のポインタとは?概念や基本的な使い方をご紹介  (1-1) はじめに  (1-2) ポインタとは? (1) C++のポインタとは?概念や基本的な使い方をご紹介 「 …

C++のtime関数やtime_t型の使い方について

  <目次> (1) C++のtime関数やtime_t型の使い方について  (1-1) C++のtime関数とtime_t型とは?  (1-2) C++のtime_t関数のサンプル (1) …

Valgrindとは?使い方や概要をご紹介(メモリリーク検知ツール)

  <目次> (1) Valgrindとは?使い方や概要をご紹介(メモリリーク検知ツール)  (1-1) Valgrindとは?  (1-2) Valgrindの導入方法  (1-3) Va …

C++における「>>」の意味について

  <目次> (1) C++における「>>」の意味について  (1-1) 概要  (1-2) サンプルプログラム  (1-3) どんな時に使われる?⇒データ圧縮  (1-4) 備 …

Valgrindで行番号を表示させる方法

  <目次> (1) Valgrindで行番号を表示させる方法  (1-1) 行番号を表示させる方法  (1-2) (参考)「-g」オプションについて (1) Valgrindで行番号を表示 …

  • English (United States)
  • 日本語
Top