ページ 11

memcpyのエラーについて

Posted: 2017年11月02日(木) 21:58
by pocket
お世話になっております。

今回簡単なmemcpyのプログラムを作成した結果、
エラーが出まして、そのエラーの原因がわからずに困っています。
ソースコードを以下に掲載します。

内容はsrcの内容をdstにコピーするというもので、中でmemcpyを使用しています。

sample.c

コード:

#include <stdio.h>
#include <string.h>
int main(){
        int    * src,*tmp;
        int    * dst;
        int     i1;
        
        tmp=src;
        for (i1 = 0; i1 < 10; i1++){
                *src = i1;
                src++;
        }

        printf("1.");
        src=tmp;
        for (i1 = 0; i1 < 10; i1++){
                printf("[%d]", *(src++));
        }
        printf("\n2.");
        src=tmp;
        memcpy(dst, src, 10);

        printf("aaa");
        for (i1 = 0; i1 < 10; i1++){
                printf("[%d]", *(dst++));
        }       
}
エラーはセグメンテーションフォルトです。
エラーの原因と、解決策についてご教授いただければ幸いです。

よろしくお願いいたします。

Re: memcpyのエラーについて

Posted: 2017年11月02日(木) 22:30
by みけCAT
未初期化の自動変数srcやdstの値は不定であり、それを使用した計算をすると未定義動作になります。
データを入れたりコピーしたりしようとする前に、srcやdstに配列やmallocなどで確保した領域など、十分な大きさをもつ有効な領域へのポインタを代入しないといけません。

Re: memcpyのエラーについて

Posted: 2017年11月05日(日) 23:31
by pocket
みけCATさん

返信いただきありがとうございます。
また、私の返信が遅くなってしまい申し訳ございません。

ご指摘いただきました通り、以下のように修正しましたが、
適切に動作しませんでした。
実行結果も合わせて記載いたします。

どの部分に不備があるのかをご指摘いただければ幸いです。
よろしくお願いいたします。

コード:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
        int    * src,*tmp;
        int    * dst;
        int     i1;
        
        src=malloc(sizeof(int)*10);
        tmp=malloc(sizeof(int)*10);
        dst=malloc(sizeof(int)*10);
        
        tmp=src;
        for (i1 = 0; i1 < 10; i1++){
                *src = i1;
                src++;
        }
 
        printf("1.");
        src=tmp;
        for (i1 = 0; i1 < 10; i1++){
                printf("[%d]", *(src++));
        }
        printf("\n2.");
        src=tmp;
        memcpy(dst, src, 10);
 
        //printf("aaa");
        for (i1 = 0; i1 < 10; i1++){
                printf("[%d]", *(dst++));
        }       
}
実行結果
1.[0][1][2][3][4][5][6][7][8][9]
2.[0][1][2][-1610612736][10][0][0][0][0][0]

Re: memcpyのエラーについて

Posted: 2017年11月05日(日) 23:44
by みけCAT
「適切に動作」の定義が書かれていないようなので断定はできませんが、27行目で10バイトしかコピーしていないのがよくなさそうですね。
ここをsizeof(int)*10バイトコピーするようにすると「適切に動作」するかもしれません。
オフトピック
tmpに確保したメモリのアドレスを代入し、その直後に他のアドレスを代入して露骨にメモリリークを発生させているのも気になりますが…大きな影響はないでしょう。

Re: memcpyのエラーについて

Posted: 2017年11月06日(月) 00:31
by pocket
みけCATさん

回答頂きがりがとうございます。
ご指摘の部分を修正したところ、動作しました。

適切な動作とは、srcの内容を正確にdstにコピーするというものです。
説明が不足しており、ご迷惑をおかけしました。

最終的なソースコードは以下になりました。
私の質問に対して考えていただいた皆様に感謝いたします。
ありがとうございました。

コード:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
        int    * src,*tmp;
        int    * dst;
        int     i1;
        
        src=malloc(sizeof(int)*10);
        //tmp=malloc(sizeof(int)*10);
        dst=malloc(sizeof(int)*10);

        tmp=src;
        for (i1 = 0; i1 < 10; i1++){
                *src = i1;
                src++;
        }
 
        printf("1.");
        src=tmp;
        for (i1 = 0; i1 < 10; i1++){
                printf("[%d]", *(src++));
        }
        printf("\n2.");
        src=tmp;
        memcpy(dst, src, sizeof(int)*10);
 
        //printf("aaa");
        for (i1 = 0; i1 < 10; i1++){
                printf("[%d]", *(dst++));
        }       
}

Re: memcpyのエラーについて

Posted: 2017年11月06日(月) 03:20
by かずま
malloc で確保した領域は、使用しなくなったら
free で解放するのがお行儀のよい作法です。
そのためには、malloc で確保した領域へのポインタは
++ などで変更しないほうが良いと思います。

src は、tmp に退避してあとで元に戻しているのでいいんですが、
dst は、++ で 10回変更されたままなので、これを free には
そのままでは使えません。
free(dst - 10); ならいいんでしょうが。

プログラムを次のようにしたほうが良いのではありませんか。

コード:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main(void)
{
    int *src, *dst, *tmp;
    int i1;
 
    src = malloc(sizeof(int)*10);
    dst = malloc(sizeof(int)*10);

    tmp = src;
    for (i1 = 0; i1 < 10; i1++)
        *tmp++ = i1;
 
    printf("1.");
    tmp = src;
    for (i1 = 0; i1 < 10; i1++)
        printf("[%d]", *tmp++);
    
    printf("\n2.");
    memcpy(dst, src, sizeof(int)*10);
 
    tmp = dst;
    for (i1 = 0; i1 < 10; i1++)
        printf("[%d]", *tmp++);

    free(src);
    free(dst);
    return 0;
}
malloc が失敗したかどうかを調べて、その対応を
入れておくともっとお行儀が良いでしょう。