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-3) …

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

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

C++の構造体とは?の作り方や使い方について

  <目次> (1) C++の構造体とは?の作り方や使い方について  (1-1) 構造体とは?  (1-2) サンプルプログラム  (1-3) 構造体の変数を定義する方法  (1-4) 構造 …

C++のlocaltime関数がスレッドアンセーフである理由と使用上の注意点

  <目次> (1) C++のlocaltime関数がスレッドアンセーフである理由と使用上の注意点  (1-1) localtime関数がスレッドアンセーフである理由  (1-2) loca …

C++の「int **g = new int*;」の意味について

  <目次> (1) C++の「int **g = new int*;」の意味について  (1-1) 「int **g = new int*;」の意味  (1-2) サンプルで理解を深める …

  • English (United States)
  • 日本語
Top