09/02/15 00:50:56
自分が開発途中で疑問に思ったことや
やりたい実装などを解決していくスレです。
最近気になった事は動的メモリ確保で発生する
フラグメンテーションについてで、例えばmallocは
内部でフラグメンテーションが発生しない様に
freeしたメモリ領域を結合(?)しているみたいな事を
どこかの本で見た記憶がありますが、
そうだと仮定して逆にHeapAllocでのメモリ確保はmallocと違って
そういったフラグメンテーションを一切考えてない領域の確保が
行われるのだろうか?
また、その場合フラグメンテーションを起こさないようにするには
どういった手順を踏めばいいのか興味があります。
2:デフォルトの名無しさん
09/02/15 00:56:53
_,ヾゝー'"'"'"ー、,; ,.:-‐―‐-.、_
,ラ 、_ ヽ,、 / \
イ r-'ー゙ "ー‐、, ミ/ ヽ
i! ,! i! ミi ,ハ i
,j i /ニ=、 ,r==、i ,,ハ ,ノヽi! ゙'レ>ヾ-、 ,!r'
i V <(・)>i i!(・)>゙!,i !!イ(・)) <.(・)>゙ i /!i
゙!ji! ., j .i_ /j i 。 。, ト-'
,ィi:. ;" ー-‐' ト' .! ,.=、 / ̄ ゙̄ー-、_
__ノ !ハ : 0 ; ,/ _,.-‐''\ ゙='' ,/
/ \\  ̄ ,// ゙ー-‐‐"
/ \.゙ー-イ ,/
3:sage
09/02/15 01:08:14
>>1
知ってるところまで書きます.間違っていたら指摘してください
mallocでは,OSに伺いを立てて,メモリを割り当ててもらっています.
freeすると,それをOSに返します.
その間に,たしかにメモリ領域のマネージメントが行われますが,
それはOSの責任で行われるので,プログラミングテクニックで
なんとかなる話ではないように思います.
システムコールの実装を調べてみると良いと思います.
おすすめの本は,LionsかUNIXカーネルの設計です.
(逆にいうと,私の知識はこれらの本くらいクラシックです)
あと,HeapAllocはよくわかりません.
スタックに対応するヒープのことを言っているのであれば,
mallocもヒープからメモリを取得していると思うんですが...
4:デフォルトの名無しさん
09/02/15 01:27:10
HeapAllocがフラグメントを考慮していないわけがない。
HeapAllocもmallocと同じく少量確保用に特化している点で同じ。
単にWin32APIと標準Cライブラリ、属すところが違うだけ。
例えば、今時のVCのmallocは単にHeapAllocを呼んでいるだけだ。
5:LTD
09/02/15 01:38:53
>>3
システムコールの実装ですか。
その辺は当然OSによって変わってくるんでしょうね。
因みにフラグメンテーションに興味を持ったのは、
今読んでいる本にそういう事が色々記載されていたからです。
※「C言語 ポインタ 完全制覇」(タイトルがなんとなく恥ずかしいけど。)
「HeapAlloc」がわからないというのはHeapAlloc自体が何なのかわからない
という勝手な解釈なんですがWindowsで提供されているAPIの事です。
(UNIXやLinuxを主に触っている方は馴染みがないでしょう)
上記のAPIもmallocと同じで最終的にメモリ確保を行うのですが。
Windows環境で動く処理系の場合mallocを呼び出すと最終的に
HeapAllocを呼ぶという事をよく聞くのですが、mallocは具体的に
どういう事をやった上でHeapAllocを呼び出しているのかが
曖昧で結局自分はHeapAllocを使っています。
その辺詳しく解説されているサイトがあれば教えて欲しい。。。
ところで「スタックに対応するヒープ」というのはどういう事でしょうか?
6:LTD
09/02/15 01:40:26
寝ます
7:デフォルトの名無しさん
09/02/15 01:42:30
>>5
簡単だよ。大雑把に言えばこういうこと。
HANDLE hHeap; // malloc用のヒープハンドル
void* malloc(size_t n)
{
return HeapAlloc(hHeap, 0, n);
}
3の言っている「スタックに対応するヒープ」ってのは、ここで話しているヒープのことのはず。
8:LTD
09/02/15 01:44:16
>>4
ありがとうございます。
「属すところが違うだけ。」
↑でなんとなく理解できました。
フラグメンテーションの結論としてはOSが管理しているから、
使う側にとってはあまり意識するものじゃないという事ですね。
(結論を出すにはまだ早すぎるかもしれませんが)
ともかく今日は寝ます
9:デフォルトの名無しさん
09/02/15 03:08:49
単発質問スレに対して丁寧に答える馬鹿
10:デフォルトの名無しさん
09/02/15 04:02:28
#include <windows.h>
DWORD test(LPVOID){return (DWORD)0;}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstp, LPSTR szCmd, int iCmd )
{
char *str=NULL;
for( int i=0; i<65535; i++)
{
for( int ii=0; ii<65535; ii++ )
{
str=new char[1024];
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)test,NULL,0,NULL);
}
}
return 0;
}
11:デフォルトの名無しさん
09/02/15 04:10:20
>>10
testにもWINAPI付けろ。
わざわざLPTHREAD_START_ROUTINEにキャストするな。
12:LTD
09/02/15 11:07:40
>>10
このコードはどういった意味があるんでしょうか?
newで動的にメモリを確保しているのはわかるんですが、
CreateThreadでスレッド生成はどういった意味を持つのでしょうか?
スタックの指定がないのでデフォルト(通常1M)のスタック領域が
割り当てられると思うのですが、通常(XP)の仮想メモリのサイズは
2Gなのでスレッド生成できる個数は2048個だと思います。(MSDNにも記載)
それに加えてnewでの仮想メモリ空間からメモリを確保(?)しているので
生成できるスレッドがもっと少なくなることの実証でしょうか?
>>11
呼び出し規約のデフォルト設定にもよりますが、
stdcallとcdeclではスタック調整のやり方が違うので
不具合の原因になりますね。
ところで少しスタックの話が出たのですが、
少し前に自動変数で全体として1Mを超えてしまう
定義をしてしまい、起動時にクラッシュしてハマった記憶があります。
色々調べた結果、スタックサイズが原因という事だったので
対処法として動的にメモリ確保かスタックを使わずstatic定義にて
モジュールにその領域分を直接埋め込むかで悩んだのですが
結局後者を採用しました。ただ、この場合は起動時に埋め込んだ領域の
初期化処理を行うはずなので、その分オーバヘッドが発生するのでは
と思うのですが、こういった1Mを超える領域を定義する場合
他の方はどういった対処で会費しているのでしょうか?
因みにある構造体を予め決められた個数分配列で定義してファイルから
全て読み込む形にしているので、全て読み込むのではなく都度読み込みに
してもよかったのですが、ファイルアクセスでのオーバーヘッドが出てくると
思ったのでstatic定義でのやり方で解決しました。
13:LTD
09/02/15 11:27:07
>>7
何度も読み返してみたのですが、微妙に理解できてない状態です。
特に「スタックに対応する」という辺りで自分の理解不足からか
思考停止してる状態ですorz
この際、視点を変えて
「結局malloc(VCの処理系)は内部で単純にHeapAllocコールしている」
という解釈で完結していいでしょうか。。。
14:デフォルトの名無しさん
09/02/15 11:27:21
ヒープかな。