peekCStringでHaskell文字列を作った後はC文字列が書き換えられてもHaskell文字列に影響はない

shiftJisからUtf16、Utf16からshiftJisへの変換では、変換した後にpeekCString、peekCWString関数によってC文字列からHaskell文字列を作ります。C文字列はHaskell文字列返す前にメモリを解放しているのですが、ふとポインタで指している領域が消えると返す値まで消えてしまうのではないかと思いました。
そこで、peekCStringでCの文字列からHaskell文字列を作った後にC文字列が書き換えられてもHaskellの文字列に影響がないことを確認します。
HaskellはpeekCString、peekCWString関数によって新しくHaskell文字列を作りますのでメモリ解放しても影響は受けません。

{-# LANGUAGE ForeignFunctionInterface #-}
--  ghc --make -Wall utf8.hs bstr.c -loleaut32 -o utf8

module Main where

import Foreign.Marshal.Alloc 
import Foreign.C.String
import Foreign.C.Types

shiftJisToUtf16 :: String -> IO String
shiftJisToUtf16 string = do
    cws <- newCWString "※※※※\n"
    bstr <- withCString string c_CStringToBSTR
    -- cswprintf bstr cws -- ここで上書きすれば出力も変わります。
    str <- peekCWString bstr
    cswprintf bstr cws -- ここで cws を上書き
    cwprintf bstr      -- 上書きした文字列を表示してみる。 "※※※※\n"
    cSysFreeString bstr  
    return str

utf16ToShiftJis :: String -> IO String
utf16ToShiftJis string = do 
    cstring <- withCWString string c_BSTRtoCString
    -- oprintf cstring  -- ここで上書きすれば出力も変わります。
    str     <- peekCString cstring
    oprintf cstring     -- ここでcstringを上書き
    cprintf cstring     --  上書きした文字列を表示してみる。 "hello,world!"
    free cstring 
    return str

-- C の関数を呼ぶための定義
foreign import ccall unsafe "CStringToBSTR"      c_CStringToBSTR   :: CString    -> IO CWString
foreign import ccall unsafe "BSTRtoCString"      c_BSTRtoCString   :: CWString   -> IO CString
foreign import stdcall "windows.h SysFreeString"     cSysFreeString      :: CWString -> IO ()
foreign import ccall "string.h strlen"  cstrlen :: CString -> CUInt
-- 同じ printf をHaskellでは2種類定義してみました。
foreign import ccall "stdio.h printf" cprintf :: CString -> IO ()
foreign import ccall "stdio.h printf" cprint2 :: CString -> CUInt -> CUInt -> IO ()
foreign import ccall "OverWriteCString" oprintf   :: CString -> IO ()
foreign import ccall "wchar.h wprintf"  cwprintf  :: CWString -> IO ()
foreign import ccall "wchar.h swprintf" cswprintf :: CWString -> CWString -> IO ()

main :: IO ()
main = do
    cstr <- newCString "%d %d\n"
    cprint2 cstr 1 2
    free cstr
    s <- utf16ToShiftJis "こんにちは"
    u <- shiftJisToUtf16 s
    putStrLn =<< (utf16ToShiftJis u)

-- $ ./utf8|nkf -w
-- こんにちは
-- 1 2
-- hello,world!
-- ※※※※
-- hello,world!
#include <stdio.h>
#include <malloc.h>
#include <windows.h>

// 上書きするための関数
char* OverWriteCString(char *cstring){
    sprintf(cstring,"hello,world!\n");
    return cstring;
}

BSTR CStringToBSTR(char* cstring ){
    int    cstringlen, out_size;
    BSTR   wstr;
    cstringlen = strlen(cstring);
    out_size   = MultiByteToWideChar(CP_ACP, 0, cstring, cstringlen, NULL, 0);
    wstr       = SysAllocStringLen(NULL, out_size);
    MultiByteToWideChar(CP_ACP, 0, cstring, cstringlen, wstr, out_size);

    return wstr;
}

char* BSTRtoCString(BSTR bstr){
    int    out_size;
    char   *cstring;
    out_size = WideCharToMultiByte(CP_ACP, 0, (OLECHAR*)bstr, -1,NULL, 0, NULL, NULL);
    cstring  = (char*)malloc((out_size+1) * sizeof(char));
    WideCharToMultiByte(CP_ACP, 0, (OLECHAR*)bstr, -1, cstring,out_size, NULL, NULL);
    return cstring;
}