LIFE LOG(ここにはあなたのブログ名)

あつあつ備忘録

ソフトやハード、時にはメカの備忘録をまとめていきます

【C++】関数からオブジェクトの返し

f:id:AtsuyaKoike:20190524095847p:plain:w300

関数にオブジェクトを渡すことができるように、返すこともできる。



#include <iostream>
#include <cstring>
using namespace std;

class samp {
    char s[80];
public:
    void show() {
        cout << s << "\n";
    }
    void set( char * str ) {
        strcpy( s, str );
    }
};

samp input() {
    char s[80];
    samp str;

    cout << "文字列の入力";
    cin >> s;

    str.set(s);

    return str;
}

int main() {
    samp ob;

    ob = input();
    ob.show();

    return 0;
}
$ g++ -o study92 study92.cpp 
$ ./study92 
文字列の入力:こんにちは
こんにちは




study93.cpp

このプログラムはコアダンプになる

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;

class samp {
    char *s;
public:
    samp() {
        s = "\0";
    }
    ~samp() {
        if( s ) {
            free( s );
            cout << "sを開放する\n";
        }
    }
    void show() {
        cout << s << "\n";
    }
    void set( char *str ) {
        s = ( char * ) malloc( strlen(str) + 1 );
        if ( !s ) {
            cout << "メモリ割り当てエラー\n";
            exit(1);
        }
        strcpy( s, str );
    }
};

samp input() {
    char s[80];
    samp str;
    cout << "文字列の入力:";
    cin >> s;

    str.set(s);
    return str;
}

int main() {
    samp ob;

    ob = input();
    ob.show();

    return 0;
}
$ ./study93 
文字列の入力:hello
sを開放する

*** Error in `./study93': double free or corruption (fasttop): 0x0000000001b00440 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7ff642cb97e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7ff642cc237a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7ff642cc653c]
./study93[0x400cc7]
./study93[0x400bfe]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7ff642c62830]
./study93[0x400a39]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:06 14298074                           /home/atsuya/study/cpp/study93
00601000-00602000 r--p 00001000 08:06 14298074                           /home/atsuya/study/cpp/study93
00602000-00603000 rw-p 00002000 08:06 14298074                           /home/atsuya/study/cpp/study93
01aee000-01b20000 rw-p 00000000 00:00 0                                  [heap]
7ff63c000000-7ff63c021000 rw-p 00000000 00:00 0 
7ff63c021000-7ff640000000 ---p 00000000 00:00 0 
7ff642939000-7ff642a41000 r-xp 00000000 08:06 13238541                   /lib/x86_64-linux-gnu/libm-2.23.so
7ff642a41000-7ff642c40000 ---p 00108000 08:06 13238541                   /lib/x86_64-linux-gnu/libm-2.23.so
7ff642c40000-7ff642c41000 r--p 00107000 08:06 13238541                   /lib/x86_64-linux-gnu/libm-2.23.so
7ff642c41000-7ff642c42000 rw-p 00108000 08:06 13238541                   /lib/x86_64-linux-gnu/libm-2.23.so
7ff642c42000-7ff642e02000 r-xp 00000000 08:06 13238538                   /lib/x86_64-linux-gnu/libc-2.23.so
7ff642e02000-7ff643002000 ---p 001c0000 08:06 13238538                   /lib/x86_64-linux-gnu/libc-2.23.so
7ff643002000-7ff643006000 r--p 001c0000 08:06 13238538                   /lib/x86_64-linux-gnu/libc-2.23.so
7ff643006000-7ff643008000 rw-p 001c4000 08:06 13238538                   /lib/x86_64-linux-gnu/libc-2.23.so
7ff643008000-7ff64300c000 rw-p 00000000 00:00 0 
7ff64300c000-7ff643023000 r-xp 00000000 08:06 13242862                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff643023000-7ff643222000 ---p 00017000 08:06 13242862                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff643222000-7ff643223000 r--p 00016000 08:06 13242862                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff643223000-7ff643224000 rw-p 00017000 08:06 13242862                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff643224000-7ff6433a0000 r-xp 00000000 08:06 6686331                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7ff6433a0000-7ff6435a0000 ---p 0017c000 08:06 6686331                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7ff6435a0000-7ff6435aa000 r--p 0017c000 08:06 6686331                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7ff6435aa000-7ff6435ac000 rw-p 00186000 08:06 6686331                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7ff6435ac000-7ff6435b0000 rw-p 00000000 00:00 0 
7ff6435b0000-7ff6435d6000 r-xp 00000000 08:06 13238524                   /lib/x86_64-linux-gnu/ld-2.23.so
7ff643782000-7ff643788000 rw-p 00000000 00:00 0 
7ff6437d4000-7ff6437d5000 rw-p 00000000 00:00 0 
7ff6437d5000-7ff6437d6000 r--p 00025000 08:06 13238524                   /lib/x86_64-linux-gnu/ld-2.23.so
7ff6437d6000-7ff6437d7000 rw-p 00026000 08:06 13238524                   /lib/x86_64-linux-gnu/ld-2.23.so
7ff6437d7000-7ff6437d8000 rw-p 00000000 00:00 0 
7ffe018df000-7ffe01901000 rw-p 00000000 00:00 0                          [stack]
7ffe01996000-7ffe01999000 r--p 00000000 00:00 0                          [vvar]
7ffe01999000-7ffe0199b000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)
  • デストラクタが3回呼び出される
    1. input()が終了し、ローカルオブジェクトのstrがスコープから外れた時
    2. input()から返される一時オブジェクトが破棄されるとき
    3. main()終了時
  • 最初のデストラクタが実行されるときにinput()関数で文字列を格納するために割り当てられたメモリが開放される
    • すでに開放されているメモリを他の2つが開放しようとする
    • 進行中の自動割当システムが破壊される
  • したがって、ストラクタやデストラクタがあるときにオブジェクトを返すときは注意が必要
  • コピーコンストラクタを使うことで解決できる(こちら)




引用・参考はこちら

f:id:AtsuyaKoike:20190524100759j:plain:w200
独習C++ 第4版 https://www.amazon.co.jp/dp/4798119768