質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2109閲覧

void*によるcvectorで、バッファオーバーランの警告

asobinin

総合スコア69

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/07/14 07:21

編集2019/07/14 10:53

void型をキャストすることでint型やconst char型、ユーザー定義型に対応するcvectorというものを試作してみました。
ところが、PUSH_BACKマクロにてバッファオーバーランが発生したとの警告が発生してしまいます。
詳細を見てみると、
ARRAY_AT(T, tmp, i) = AT(T, CVECTOR, i);
AT(T, CVECTOR, CVECTOR.size_) = ITEM;
の二か所で「書き込み中にバッファオーバーランが発生しました。8バイト(テストケースの場合)を書き込む可能性があります。」という警告が出されています。
ITEMの代入はともかくとして、tmpとCVECTORは同じ型のはずなのに何故このような警告が出されているのでしょうか。

開発環境:VisualStudio2019 OS:Windows10

C

1// main.c 2#include <stdio.h> 3#include "cvector.h" 4 5int main(void) 6{ 7 cvector test; 8 INIT(test); 9 int size = 20; 10 for (int i = 0; i < size; i++) { 11 PUSH_BACK(int, test, i * i); 12 } 13 for (int i = 0; i < size; i++) { 14 printf("%d\n", AT(int, test, i)); 15 } 16 17 CLEAR(test); 18 return 0; 19}

C

1// cvector.h 2#pragma once 3#include <stdlib.h> 4#include <stdio.h> 5 6// C言語による簡易vectorもどき 7typedef struct cvector_t { 8 void* data_; // 要素の格納領域 9 int capacity_; // 格納可能な最大要素数 10 int size_; // 格納されている要素数 11} cvector; 12 13// 初期化 14#define INIT(CVECTOR) CVECTOR.data_ = 0; CVECTOR.capacity_ = 0; CVECTOR.size_ = 0; 15 16// 配列への参照(汎用) 17#define ARRAY_AT(T, V, N) ((T*)V)[N] 18 19// 要素への参照(cvector) 20#define AT(T, CVECTOR, N) ARRAY_AT(T, CVECTOR.data_, N) 21 22// 要素の末尾にデータを追加 23#define PUSH_BACK(T, CVECTOR, ITEM)\ 24{\ 25 if (CVECTOR.size_ == CVECTOR.capacity_) {\ 26 CVECTOR.capacity_ += 10;\ 27 void* tmp;\ 28 tmp = (T*)malloc(sizeof(T) * CVECTOR.capacity_);\ 29 if (tmp == NULL) { printf("memory secure error\n"); exit(1); }\ 30 for (int i = 0; i < CVECTOR.size_; ++i)\ 31 ARRAY_AT(T, tmp, i) = AT(T, CVECTOR, i);\ 32 FREE(CVECTOR);\ 33 CVECTOR.data_ = tmp;\ 34 }\ 35 AT(T, CVECTOR, CVECTOR.size_) = ITEM;\ 36 CVECTOR.size_++;\ 37} 38 39// 全ての要素を消去する 40#define CLEAR(CVECTOR) free(CVECTOR.data_); CVECTOR.capacity_ = 0; CVECTOR.size_ = 0; 41 42// data_のみを消去する 43#define FREE(CVECTOR) free(CVECTOR.data_);

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

izmktr

2019/07/14 10:02

コンストラクタがないC言語では、cvector_tの初期化は使えないと思うんですけど、C++としてコンパイルしていませんか?
asobinin

2019/07/14 10:13

見落としておりました。 修正致します。
y_waiwai

2019/07/14 12:53

そのでているワーニングメッセージを、手を加えす、コピペで提示してください
asobinin

2019/07/14 13:05

ワーニングメッセージを確認しようとしたところ、警告が消えていたことを確認しました・・・ テストしてみたところ、INIT()による初期化では警告は発生せず、コントラスタにて初期化を行っていた場合においては警告が発生するようです。コントラスタで初期化した後、INIT()で再度初期化しても警告は発生しませんでした。 どちらも同様のことをしておりますが、何故このようなことが起きているのでしょうか。
asobinin

2019/07/14 13:06

ワーニングメッセージ全文 警告 C6386 'test.data_' への書き込み中にバッファー オーバーランが発生しました: 書き込み可能なサイズは 'sizeof(int)*test.capacity_' バイトですが、'test.size_' バイトを書き込む可能性があります。 警告 C6386 'tmp' への書き込み中にバッファー オーバーランが発生しました: 書き込み可能なサイズは 'sizeof(int)*test.capacity_' バイトですが、'8' バイトを書き込む可能性があります。
pepperleaf

2019/07/14 14:28

[参考] VS 2017 Express では、エラー無しで終了。 環境: WIndows10 64bit
guest

回答1

0

ベストアンサー

VisualStudio2019、Windows10 64bit環境です。

CVECTOR.size_とCVECTOR.capacity_の値によってはバッファオーバーランが発生するかもしれない。
という警告かと思われます。

PUSH_BACK実行時、仮に両方の変数に-10が設定されていた場合は、
mallocの時点でCVECTOR.capacity_が0になっているはずなので、サイズ0でmallocを呼びます。

処理系によってはmallocに0を渡すとNULL以外を返します。
その場合は次の行のif (tmp == NULL)をすり抜けます。

すり抜けた先で、もしこのままtmpにアクセスすることがあったらバッファオーバーランが発生しますよ?
という警告に読み取れます。

c

1// 要素の末尾にデータを追加 2#define PUSH_BACK(T, CVECTOR, ITEM)\ 3{\ 4 if(CVECTOR.size_ >= 0 && CVECTOR.capacity_ >= 0 ){\ 5 省略 6 }/ 7}

両方0以上で通るようにしたら警告は発生しませんでした。

投稿2019/07/15 03:13

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問