![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
お世話になります。
メモリ領域の確保の仕方とポインタの動向についての質問です。
呼び出し側の関数testで領域Aを確保する。
関数test内で確保した領域に作業領域Bを加え作業をする。
関数testを抜けるときにreallocで呼び出し側から得た
サイズに領域Aを戻す。
このときの動作についてなんですが
//呼び出し側
void Main(){
DATA *data_p;//データ構造体
long datacount = 5;//データ数(5はテスト用の可変値
data_p = (DATA*)malloc(sizeof(DATA)*datacount);
test(data_p,datacount);
free((void*)(data_p);
}
//関数test
test(DATA data[],long datacount){
DATA *sagyodata_p;
long a = datacount+5;
sagyodata_p = data;
//作業用に領域を広げる
sagyodata_p = (DATA*)malloc(sizeof(DATA)*a);
//領域サイズを戻す
realloc(((void*)sagyodata_p),sizeof(DATA)*datacount);
}
としたときに
関数testでdata_pを参照したポインタsagyodata_pの中身は問題ないでしょうか?
現在の実行環境 .NET2003 C++では問題なく動いているようですが。
sagyodata_p = data;
sagyodata_p = (DATA*)malloc(sizeof(DATA)*a);
とするより、
realloc(((void*)data),sizeof(DATA)*a);
としたほうがよいのでしょうか?
この2つの違いがどのくらいあるのかお教えいただけたら
助かります。
よろしくお願いします。
No.3ベストアンサー
- 回答日時:
メモリリークしています。
> //作業用に領域を広げる
> sagyodata_p = (DATA*)malloc(sizeof(DATA)*a);
によって,以降(せっかく渡された)dataの指すオブジェクトではなく
新たに確保された領域に対して操作することになります。
しかも,freeしていません。
渡されたdataのサイズを変更したいのであればdataをreallocしましょう。
現状,Mainで確保したdata_pはtest使われずにそのままfreeされています。
・キャストについて
void*へのキャストは冗長なだけです。
# その逆はC++のことを考えるとしてもいいかも。
#include<stdlib.h>
typedef int DATA; // 構造体の代わり
void test(DATA ** data, long datacount){
long a = datacount + 5;
void * tmp;
//作業用に領域を広げる
if ((tmp = realloc(*data, sizeof(DATA)*a)) == NULL){
return; // 適当に復旧
}
*data = tmp;
// ここでdataをごにょごにょ
// :
//領域サイズを戻す
if((tmp = realloc(*data, sizeof(DATA)*datacount)) == NULL){
return; // 適当に復旧
}
*data = tmp;
}
int main(void){
DATA *data_p;
long datacount = 5;
data_p = malloc(sizeof(DATA)*datacount);
test(&data_p, datacount);
free(data_p);
}
御回答頂いた内容でずいぶんすっきりしました。
> sagyodata_p = (DATA*)malloc(sizeof(DATA)*a);
によって,以降(せっかく渡された)dataの指すオブジェクトではなく
新たに確保された領域に対して操作することになります。
sagyodata_p=data;で作業領域はdataを指すけれども
関数testによって新たに追加された領域は
現状たまたまうまくいっているようにみえるだけで
実際どこに確保されるかは分からないということですね。
分かりやすい御回答どうもありがとうございました。
No.5
- 回答日時:
失礼。
ANo.4の下から3行目を修正します。> memcpy(data, temporary, sizeof(DATA) * temporarySize);
memcpy(data, temporary, sizeof(DATA) * datacount);
No.4
- 回答日時:
条件は次の通りでよろしいですか?
1.test関数の型は変更できない。
2.dataが指すDATA構造体(の配列)には変更を加える。
3.testを呼ぶ前とmainに帰ってきたときのサイズ(配列の要素数)は同じ
だとしたらreallocを使わずにすみ,
めんどくさい事(ポインタの書き換えとか)を一切する必要がなくなりますね。
#include<stdlib.h>
#include<string.h>
typedef int DATA;
void test(DATA data[], long datacount){
const int temporarySize = datacount + 5;
DATA * temporary = malloc(sizeof(DATA) * temporarySize);
if (!temporary)return;
memcpy(temporary, data, sizeof(DATA) * datacount);
// ここでtemporaryをごにょごにょする
memcpy(data, temporary, sizeof(DATA) * temporarySize);
free(temporary);
}
たびたびの御回答ありがとうございます。
その後考えた結果RISKさんと同じ方法で
(memcpyを使う)
記述することにしました。
お力添え大変ありがとうございました。
No.2
- 回答日時:
このプログラムよく見たら、realloc(((void*)sagyodata_p),sizeof(DATA)*datacount);
が、sagyodata_pと同じアドレス返却してるから、たまたま動いてるけど正しくは
//呼び出し側
void Main(){
・・・
test(&data_p,datacount);
free((void*)(data_p);
}
//関数test
test(DATA **data,long datacount){
・・・
*data = realloc(((void*)*data ),sizeof(DATA)*datacount);
}
#必要部分しか書いてません。
ってしないと、変な所free()する可能性が有りそうです。
No.1
- 回答日時:
っていうか、realloc()の返却値はエラーチェックした方が良さそうです。
realloc()すれば、mallocした後、元の領域からコピーする手間が減るんじゃないですか?
参考URL:http://www9.plala.or.jp/sgwr-t/lib/realloc.html
早速の御回答どうもありがとうございます。
参考URL拝見しました。
成功してもアドレスが同じだとは限らないのですね・・・
>realloc()すれば、mallocした後、元の領域からコピーする手間が減るんじゃないですか?
元々作業領域のサイズを変えずに書いていたコードだったので
コード記述上sagyodata_p = data;としていました。
No2に書いていただいた内容を自分でもう一度考えて見たいと思います。
test(DATA data[],long datacount)の引数型が現状変更できないのです。
後ほど補足させて頂くかも知れませんが、そのときにお時間が許せば
再度お力をお貸しいただけたら幸いです。
どうもありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- その他(プログラミング・Web制作) pythonでDBのカラム名で取得したオブジェクトの値を表示したい 1 2022/05/13 03:41
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- Excel(エクセル) 何方か知恵をください… 下記のシート1にシート2のDATAを表示させたいです。 (シート1の2行目の 6 2022/03/28 17:27
- C言語・C++・C# プログラミングの問題です。写真のプログラムの1から10を下のように入力しましたがプログラムが上手くい 3 2022/07/01 23:31
- C言語・C++・C# pythonのファイルの並びでの読み込みとリストについて 4 2022/04/13 03:52
- CPU・メモリ・マザーボード デスクトップPCのOS(C:)の空き領域がどんどん減ります。 9 2022/12/12 09:24
- その他(Microsoft Office) Excel 2列分のDATAの並べ替え 1 2023/01/01 17:12
- その他(プログラミング・Web制作) Python - Excel で Webからデータを連続取得したいのですが エラーが出ます 1 2023/07/06 20:08
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ポインター引数の関数でコンパ...
-
stable diffusionのエラー
-
C言語の構造体にてバブルソート...
-
int型(2バイト)データの分割
-
c言語での wavファイルの編集(...
-
C++/CLIのオブジェクト型配列
-
pythonでDBのカラム名で取得し...
-
二次元配列
-
チェックボックスからの値を受...
-
連想配列をリターン値として返...
-
構造体のソートの方法について...
-
【Excel VBA】10進数を2進数に...
-
結城未来さんの年齢
-
c言語の多次元配列で1から100ま...
-
linuxのシェルでファイル名に先...
-
花の名前を教えてください。
-
Perl マッチング 1行だけ表示
-
この花の名前を教えてください。
-
'dataType' 引数を Null にする...
-
RegQueryValueExでの2バイト文字
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ポインター引数の関数でコンパ...
-
stable diffusionのエラー
-
printfの%eで指数部分の桁数を...
-
【Excel VBA】10進数を2進数に...
-
int型(2バイト)データの分割
-
pythonでDBのカラム名で取得し...
-
エクセルVBA:日付データの変換...
-
C#でのswitch文
-
linuxのシェルでファイル名に先...
-
C言語の構造体にてバブルソート...
-
c言語での wavファイルの編集(...
-
'dataType' 引数を Null にする...
-
H8/36064を使ったシリアル通信...
-
オセロゲーム 2次元配列で困...
-
10個の実数に対する降順ソート...
-
c言語の多次元配列で1から100ま...
-
c言語 配列から数字だけをint型...
-
matlabのソースコードをpython...
-
Cのプログラムがどうしても動き...
-
テキストファイルの結合について
おすすめ情報