任意のタイミング,サイズで配列を作る方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら

トピックに返信する


答えを正確にご入力ください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: 任意のタイミング,サイズで配列を作る方法

Re: 任意のタイミング,サイズで配列を作る方法

#9

by みけCAT » 3年前

あたっしゅ さんが書きました:
3年前
やっぱ、static int* a; を free(a); しちゃ、まずいだろ。
static int* a;はヌルポインタに初期化され、
freeにヌルポインタを渡した場合は何もしないと決まっているので、問題ないはずです。

また、#6ではmallocに0を渡しているようですが、malloc(0)が何を返すかは処理系定義です。
#6の例では、malloc(0)はヌルポインタではないポインタを返すタイプの処理系であり、
その返されたポインタをfreeしていないため、メモリリークの発生として検出されているようですね。

以下、N1570より引用

6.7.9 Initialization
If an object that has static or thread storage duration is not initialized
explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
7.22.3.3 The free function
If ptr is a null pointer, no action occurs.
J.3 Implementation-defined behavior
J.3.12 Library functions
Whether the calloc, malloc, and realloc functions return a null pointer or a
pointer to an allocated object when the size requested is zero (7.22.3).
7.22.3 Memory management functions
If the size of
the space requested is zero, the behavior is implementation-defined: either a null pointer
is returned, or the behavior is as if the size were some nonzero value, except that the
returned pointer shall not be used to access an object.

Re: 任意のタイミング,サイズで配列を作る方法

#8

by あたっしゅ » 3年前

> 私にはなにやらよく分かりませんが、みけCATさんのサンプルに問題がある感じですか。

そうです。

Re: 任意のタイミング,サイズで配列を作る方法

#7

by 4700 » 3年前

みけCATさん、
回答ありがとうございます
どうしてそのようなことをしたいのですか?
質問を受けて、長々とやりたいことを書き綴って整理しておりましたら、今気づきました。

この構造体が次回呼び出し時まで値を保持しておく必要は無く、
ただ単に確保と破棄を繰り返すのが、「基本グローバル変数しか存在しないような言語」を触っていたせいで気持ち悪かっただけで、
呼び出しのたびに確保する形でも良かったのかも知れません。

確かに、問題は私の思い込みや設計だと思います。
それらを他人に教えて貰う方法について心当たりがなく、c言語の問題まで自分で絞って質問しました。
よく考えず質問してしまいすみませんでした。

回答して頂きありがとうございました。精進します!

確保直後に解放してたのは、何考えてたんでしょうね・・・多分解放してないのが怖かったんだと思います。
サンプルまで添えて頂き、ありがとうございます。

あたっしゅさん、
私にはなにやらよく分かりませんが、みけCATさんのサンプルに問題がある感じですか。

Re: 任意のタイミング,サイズで配列を作る方法

#6

by あたっしゅ » 3年前

Windows 10 PRO(64bit)
visual studio 2019
mikufree.cpp

コード:

#include <stdlib.h>
//
// https://urashita.com/archives/1271
// Visual Studio C++でメモリリークの検出
//   crtdbg.h CrtSetDbgFlag C言語のアクセス違反の調査 | urashita.com 浦下.com(ウラシタドットコム)(ja)
//
#include <crtdbg.h>
#define malloc(X) _malloc_dbg(X,_NORMAL_BLOCK, __FILE__,__LINE__)
#define new       ::new(_NORMAL_BLOCK, __FILE__,__LINE__ )
//
//
//
void
f(int n)
{
	static int* a;

	free(a);
	a = (int*)malloc(sizeof(int) * n);

	return;
}


int
main()
{
	_CrtSetDbgFlag(
		_CRTDBG_ALLOC_MEM_DF
		| _CRTDBG_DELAY_FREE_MEM_DF
		| _CRTDBG_CHECK_ALWAYS_DF
		| _CRTDBG_LEAK_CHECK_DF
	);
	f(0);
	return EXIT_SUCCESS;
}


// end.
出力
8<---------------------------
Detected memory leaks!
Dumping objects ->
C:\Users\MrAtassyu\Documents\2020x02\2019H31-01-01Atassyxx86\CBDxlibUnilove0Cuda-2020R02-12-19\MikuFree\MikuFree\MikuFree.cpp(18) : {90} normal block at 0x00B27CF8, 0 bytes long.
Data: <> -P{]ŸØîþÿÿÿˆùo
Object dump complete.
8<---------------------------
やっぱ、static int* a; を free(a); しちゃ、まずいだろ。

Re: 任意のタイミング,サイズで配列を作る方法

#5

by みけCAT » 3年前

4700 さんが書きました:
3年前
呼び出された時に、要素数nの配列を確保して破棄しない(static付けた時のように)関数を作りたいんですけど、
どうしてそのようなことがしたいのですか? (The XY Problemの疑いがあります)
4700 さんが書きました:
3年前

コード:

#include <stdlib.h>
void main(){return;}
void f (int n)
{
	static int* a;
	a = (int*)malloc(sizeof(int)*n);
	free(a);
	return;
}
このプログラムは、この質問の回答としては間違っています。
free(a);にとり、せっかく確保した配列が破棄されてしまいます。

コード:

#include <stdlib.h>
void main(){return;}
void f (int n)
{
	static int* a;
	free(a);
	a = (int*)malloc(sizeof(int)*n);
	return;
}
とすると、free(a);により前に確保した配列を破棄し(メモリリーク防止)、新しい配列を残すことができます。

Re: 任意のタイミング,サイズで配列を作る方法

#4

by みけCAT » 3年前

staticでなくてよければ、gcc拡張、もしくはC99の仕様で可変長配列(VLA : Variable-Length Array)が使えます。

コード:

void main(){return;}
void f (int n)
{
	int a[n];
	return;
}
【追記】
すいません、質問をよく読んでいませんでした。
「確保して解放しない」というのが条件なのですね。

Re: 任意のタイミング,サイズで配列を作る方法

#3

by 4700 » 3年前

回答ありがとうございます。
すみません、あまり知識がないので、これがそういう方向の話なのか分かりません・・・
「メモリを動的に確保する」感じの話ではあると思います。
Cを使いたいので、mallocが使えそうだったので使ってみました。

コード:

#include <stdlib.h>
void main(){return;}
void f (int n)
{
	static int* a;
	a = (int*)malloc(sizeof(int)*n);
	free(a);
	return;
}
無事コンパイル通りました。ありがとうございます。
しかし、なんだか大げさな感じがしてしまいます。
何と言えばいいか分かりませんが、もうすこし質素な、
ヘッダファイルが要らないようなやり方で、どうにかする方法はないのでしょうか。

Re: 任意のタイミング,サイズで配列を作る方法

#2

by usao » 3年前

malloc (C言語) だとか,
new とか STL (C++言語) とか,
そういう方向の話ですか?

任意のタイミング,サイズで配列を作る方法

#1

by 4700 » 3年前

gcc 6.3.0
質問です。
呼び出された時に、要素数nの配列を確保して破棄しない(static付けた時のように)関数を作りたいんですけど、以下のようにすると、

コード:

void main(){return;}
void f (int n)
{
	static int a[n];
	return;
}
error: storage size of 'a' isn't constant
サイズが不明でエラーになるみたいです。
任意のサイズとタイミングで確保できれば、別に関数である必要はないのですが、
なんとかこれを実装する方法はありますか。

ページトップ